Skip to content

Commit 91972e5

Browse files
committed
feat: add configurable MySQL session timeout to prevent disconnection during long operations
Add session_timeout_sec configuration parameter to prevent MySQL connection timeouts during long-running operations such as snapshot building. The timeout is applied to both wait_timeout and interactive_timeout session variables. Changes: - Add session_timeout_sec to MySQL configuration (default: 3600 seconds) - Implement session timeout setting in Connection::Connect() - Add validation (min: 60, max: 86400 seconds) - Add timeout hints in error messages for connection failures - Update documentation (EN/JA) with SELECT privilege requirements - Add comprehensive unit tests for timeout configuration - Update example configs and RPM packaging - Remove unused test-diff.conf.example file This prevents "MySQL server has gone away" errors during operations that exceed the default MySQL timeout (typically 8 hours, but can be lower).
1 parent 3d99aff commit 91972e5

File tree

16 files changed

+288
-87
lines changed

16 files changed

+288
-87
lines changed

.test-diff.conf.example

Lines changed: 0 additions & 73 deletions
This file was deleted.

docs/en/configuration.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ mysql:
107107
binlog_format: "ROW" # Binary log format (required: ROW)
108108
binlog_row_image: "FULL" # Row image format (required: FULL)
109109
connect_timeout_ms: 3000 # Connection timeout in milliseconds
110+
session_timeout_sec: 3600 # Session timeout in seconds (default: 3600 = 1 hour)
111+
# Prevents disconnection during long operations like snapshot building
110112

111113
# SSL/TLS settings (optional but recommended for production)
112114
ssl_enable: false # Enable SSL/TLS
@@ -129,6 +131,7 @@ mysql:
129131
| `binlog_format` | string | `ROW` | Binary log format (must be ROW) | ❌ No |
130132
| `binlog_row_image` | string | `FULL` | Row image format (must be FULL) | ❌ No |
131133
| `connect_timeout_ms` | integer | `3000` | Connection timeout in milliseconds | ✅ Yes |
134+
| `session_timeout_sec` | integer | `3600` | Session timeout in seconds - prevents disconnection during long operations like snapshot building | ✅ Yes |
132135
| `ssl_enable` | boolean | `false` | Enable SSL/TLS connection | ✅ Yes |
133136
| `ssl_ca` | string | `` | Path to CA certificate file | ✅ Yes |
134137
| `ssl_cert` | string | `` | Path to client certificate file | ✅ Yes |

docs/en/replication.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,24 @@ Create a user with replication privileges:
4848
-- Create replication user
4949
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'your_password';
5050

51-
-- Grant replication privileges
51+
-- Grant replication privileges (for binlog reading and GTID information)
5252
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl_user'@'%';
5353

54+
-- Grant SELECT privilege for snapshot creation (REQUIRED)
55+
-- Note: SELECT privilege on target tables is necessary for snapshot building
56+
GRANT SELECT ON database_name.table_name TO 'repl_user'@'%';
57+
5458
-- Apply changes
5559
FLUSH PRIVILEGES;
5660
```
5761

62+
**Important Notes:**
63+
64+
1. **REPLICATION CLIENT privilege is required**: Necessary for retrieving GTID information
65+
2. **SELECT privilege is required**: Necessary for reading table data during initial snapshot creation
66+
3. **No restart required**: `GRANT` statements are applied online and take effect immediately
67+
4. **Principle of least privilege**: When synchronizing multiple tables, grant SELECT privilege for each table individually
68+
5869
### Security Considerations
5970

6071
- MySQL credentials are transmitted in plain text unless your MySQL server requires TLS. Place MygramDB close to MySQL on a trusted network, or terminate TLS/SSH tunnels in front of it when replicating across untrusted links.

docs/ja/configuration.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ mysql:
107107
binlog_format: "ROW" # バイナリログ形式(必須: ROW)
108108
binlog_row_image: "FULL" # 行イメージ形式(必須: FULL)
109109
connect_timeout_ms: 3000 # 接続タイムアウト(ミリ秒)
110+
session_timeout_sec: 3600 # セッションタイムアウト(秒、デフォルト: 3600 = 1時間)
111+
# スナップショット作成などの長時間処理中の切断を防ぐ
110112

111113
# SSL/TLS設定(オプションだが本番環境では推奨)
112114
ssl_enable: false # SSL/TLSを有効化
@@ -129,6 +131,7 @@ mysql:
129131
| `binlog_format` | string | `ROW` | バイナリログ形式(ROWである必要がある) | ❌ 不可 |
130132
| `binlog_row_image` | string | `FULL` | 行イメージ形式(FULLである必要がある) | ❌ 不可 |
131133
| `connect_timeout_ms` | integer | `3000` | 接続タイムアウト(ミリ秒) | ✅ 可能 |
134+
| `session_timeout_sec` | integer | `3600` | セッションタイムアウト(秒) - スナップショット作成などの長時間処理中の切断を防ぐ | ✅ 可能 |
132135
| `ssl_enable` | boolean | `false` | SSL/TLS接続を有効化 | ✅ 可能 |
133136
| `ssl_ca` | string | `` | CA証明書ファイルへのパス | ✅ 可能 |
134137
| `ssl_cert` | string | `` | クライアント証明書ファイルへのパス | ✅ 可能 |

docs/ja/replication.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,24 @@ SET GLOBAL binlog_format = ROW;
4848
-- レプリケーションユーザーを作成
4949
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'your_password';
5050

51-
-- レプリケーション権限を付与
51+
-- レプリケーション権限を付与(binlog読み取りとGTID情報取得用)
5252
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl_user'@'%';
5353

54+
-- スナップショット作成用のSELECT権限を付与(必須)
55+
-- 注意: 対象テーブルに対するSELECT権限が必要です
56+
GRANT SELECT ON database_name.table_name TO 'repl_user'@'%';
57+
5458
-- 変更を適用
5559
FLUSH PRIVILEGES;
5660
```
5761

62+
**重要な注意事項:**
63+
64+
1. **REPLICATION CLIENT権限は必須**: GTID情報を取得するために必要です
65+
2. **SELECT権限は必須**: 初期スナップショット作成時にテーブルデータを読み取るために必要です
66+
3. **権限の追加は再起動不要**: `GRANT`文はオンラインで即座に反映されます
67+
4. **最小権限の原則**: 複数のテーブルを同期する場合は、各テーブルごとにSELECT権限を付与してください
68+
5869
### セキュリティ上の注意
5970

6071
- MySQL が TLS を必須にしていない場合、MygramDB から送信される資格情報は平文のままになります。信頼できるネットワーク内に配置するか、TLS/SSH トンネルなどで暗号化された経路を確保してください。

examples/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"binlog_format": "ROW",
1010
"binlog_row_image": "FULL",
1111
"connect_timeout_ms": 3000,
12+
"session_timeout_sec": 3600,
1213
"ssl_enable": false
1314
},
1415
"tables": [

examples/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ mysql:
2020
binlog_format: "ROW" # Binary log format (default: ROW, required for replication)
2121
binlog_row_image: "FULL" # Row image format (default: FULL, required for replication)
2222
connect_timeout_ms: 3000 # Connection timeout in milliseconds (default: 3000)
23+
session_timeout_sec: 3600 # Session timeout in seconds (default: 3600 = 1 hour)
24+
# Prevents disconnection during long operations like snapshot building
2325
# SSL/TLS settings (optional but highly recommended for production)
2426
ssl_enable: false # Enable SSL/TLS (default: false)
2527
# ssl_ca: "/path/to/ca-cert.pem" # CA certificate for SSL/TLS

src/app/server_orchestrator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ mygram::utils::Expected<void, mygram::utils::Error> ServerOrchestrator::Initiali
212212
mysql_config.connect_timeout = deps_.config.mysql.connect_timeout_ms / kMillisecondsPerSecond;
213213
mysql_config.read_timeout = deps_.config.mysql.read_timeout_ms / kMillisecondsPerSecond;
214214
mysql_config.write_timeout = deps_.config.mysql.write_timeout_ms / kMillisecondsPerSecond;
215+
mysql_config.session_timeout_sec = deps_.config.mysql.session_timeout_sec;
215216
mysql_config.ssl_enable = deps_.config.mysql.ssl_enable;
216217
mysql_config.ssl_ca = deps_.config.mysql.ssl_ca;
217218
mysql_config.ssl_cert = deps_.config.mysql.ssl_cert;
@@ -440,6 +441,7 @@ mygram::utils::Expected<void, mygram::utils::Error> ServerOrchestrator::HandleMy
440441
.connect_timeout = static_cast<uint32_t>(new_config.mysql.connect_timeout_ms / kMillisecondsPerSecond),
441442
.read_timeout = static_cast<uint32_t>(new_config.mysql.read_timeout_ms / kMillisecondsPerSecond),
442443
.write_timeout = static_cast<uint32_t>(new_config.mysql.write_timeout_ms / kMillisecondsPerSecond),
444+
.session_timeout_sec = static_cast<uint32_t>(new_config.mysql.session_timeout_sec),
443445
.ssl_enable = new_config.mysql.ssl_enable,
444446
.ssl_ca = new_config.mysql.ssl_ca,
445447
.ssl_cert = new_config.mysql.ssl_cert,

src/config/config-schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@
7777
"minimum": 1000,
7878
"maximum": 86400000
7979
},
80+
"session_timeout_sec": {
81+
"type": "integer",
82+
"description": "Session timeout in seconds (wait_timeout and interactive_timeout) - prevents disconnection during long operations like snapshot building",
83+
"default": 3600,
84+
"minimum": 60,
85+
"maximum": 86400
86+
},
8087
"ssl_enable": {
8188
"type": "boolean",
8289
"description": "Enable SSL/TLS for MySQL connection",

src/config/config.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ MysqlConfig ParseMysqlConfig(const json& json_obj) {
104104
if (json_obj.contains("write_timeout_ms")) {
105105
config.write_timeout_ms = json_obj["write_timeout_ms"].get<int>();
106106
}
107+
if (json_obj.contains("session_timeout_sec")) {
108+
config.session_timeout_sec = json_obj["session_timeout_sec"].get<int>();
109+
}
107110
if (json_obj.contains("ssl_enable")) {
108111
config.ssl_enable = json_obj["ssl_enable"].get<bool>();
109112
}

0 commit comments

Comments
 (0)