著者は、mysqldump ビルド レプリケーションの失敗の問題分析プロセスと改善提案を詳細に分析しました。
著者: 李福強
Acson DBA チームのメンバーで、MySQL、TiDB、OceanBase、その他のデータベースに精通しています。正しいことをしっかり続けていけば、また違った収穫があると思います。
この記事の出典: 元の寄稿
- Aikesheng オープンソース コミュニティによって作成されており、オリジナルのコンテンツを許可なく使用することはできません。転載する場合は編集者に連絡し、出典を明示してください。
症状
お客様から、mysqldump を使用してスレーブ ライブラリを構築すると、レプリケーションの開始後にレプリケーション エラーが発生すると報告されましたCould not execute Write_rows event on table xxx; Duplicate entry 'xxx' for key 'PRIMARY'
。
クライアントが使用するコマンド (問題ないようです)。
-- 主库备份
shell> mysqldump -uroot -pxxx --master-data=2 --single-transaction -A --routines --events --triggers >/tmp/xxx.sql
-- 从服务器还原备份并启动复制
mysql>reset master;
mysql>reset slave all;
mysql>source /tmp/xxx.sql ;
mysql>change master to master_host='xxx',master_port=3306,master_user='xxx',master_password='xxx',master_auto_position=1;
mysql>start slave;
トラブルシューティング
レプリケーション エラー テーブルのテーブル構造を確認し、テーブルのストレージ エンジンが MyISAM エンジンであることを確認します。お客様からのフィードバックによると、テーブルアクセスが頻繁であり、mysqldump --single-transaction
このオプションでは InnoDB エンジンのテーブルバックアップの整合性のみ保証できますが、MyISAM エンジンのテーブルバックアップの整合性は保証できないという点に問題がある可能性があります。
問題が解決しました
テーブルのストレージ エンジンを InnoDB に変更した後、再度バックアップと復元を行うと、スレーブ ライブラリが正常に構築できるようになります。
問題の再発
以下で問題を再現してみましょう。
環境情報
オペレーティング·システム | CentOS Linux リリース 7.5.1804 (コア) |
バージョン | MySQL 5.7.25 |
メインライブラリ | 10.186.60.187 |
図書館から | 10.186.60.37 |
マスタースレーブ | GTID を有効にする |
ステップ
メイン ライブラリで、Sysbench を使用して 1000w データを含む InnoDB エンジン テーブルを作成しますtestdb_innodb.sbtest1
(1000w データを作成する主な目的は、InnoDB エンジン テーブルのバックアップ時間を長くすることです)。
shell> sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--mysql-host=10.186.60.187 --mysql-port=3307 --mysql-user=root \
--mysql-password=1 --mysql-db=testdb_innodb --oltp-table-size=10000000 --oltp-tables-count=1 --threads=4 --report-interval=3 prepare
-- 表结构如下
mysql> show create table testdb_innodb.sbtest1;
CREATE TABLE `sbtest1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`pad` char(60) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
-- 表总行数如下:
mysql> select count(*) from testdb_innodb.sbtest1;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
メインデータベースに MyISAM エンジンのテーブルを作成しますtestdb_myisam.sbtest2
。
-- 表结构如下:
mysql> CREATE TABLE testdb_myisam.`sbtest2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`pad` char(60) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=myisam AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
メイン ライブラリで、mysqldump 論理バックアップを開始し、バックアップ中にテーブルにデータを挿入しますtestdb_innodb.sbtest1
(バックアップ順序: 最初にtestdb_innodb
ライブラリをバックアップします) 。testdb_myisam.sbtest2
-- 执行 mysqldump 备份
shell> /data/mysql/base/5.7.25/bin/mysqldump -h10.186.60.187 -P3307 -uroot -p1 --master-data=2 --single-transaction -A --routines --events --triggers >/tmp/dump.sql
-- 执行备份 testdb_innodb.sbtest1 期间,往 testdb_myisam.sbtest2 表插入一条数据
mysql> insert into testdb_myisam.`sbtest2`(k,c,pad) values(2,'myisam','myisam');
-- 通过 MySQL general_log 观察备份情况
2023-07-11T16:15:50.900581+08:00 2692 Connect [email protected] on using TCP/IP
2023-07-11T16:15:50.901124+08:00 2692 Query /*!40100 SET @@SQL_MODE='' */
2023-07-11T16:15:50.901529+08:00 2692 Query /*!40103 SET TIME_ZONE='+00:00' */
2023-07-11T16:15:50.901743+08:00 2692 Query FLUSH /*!40101 LOCAL */ TABLES
2023-07-11T16:15:50.938083+08:00 2692 Query FLUSH TABLES WITH READ LOCK
2023-07-11T16:15:50.938281+08:00 2692 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2023-07-11T16:15:50.938410+08:00 2692 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
2023-07-11T16:15:50.938678+08:00 2692 Query SHOW VARIABLES LIKE 'gtid\_mode'
2023-07-11T16:15:50.980335+08:00 2692 Query SELECT @@GLOBAL.GTID_EXECUTED
2023-07-11T16:15:50.980566+08:00 2692 Query SHOW MASTER STATUS
2023-07-11T16:15:50.980758+08:00 2692 Query UNLOCK TABLES
...略
2023-07-11T16:15:51.541911+08:00 2692 Init DB testdb_innodb
2023-07-11T16:15:51.542012+08:00 2692 Query SHOW CREATE DATABASE IF NOT EXISTS `testdb_innodb`
2023-07-11T16:15:51.542139+08:00 2692 Query SAVEPOINT sp
2023-07-11T16:15:51.542224+08:00 2692 Query show tables
2023-07-11T16:15:51.542405+08:00 2692 Query show table status like 'sbtest1'
2023-07-11T16:15:51.543353+08:00 2692 Query SET SQL_QUOTE_SHOW_CREATE=1
2023-07-11T16:15:51.543467+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:15:51.543548+08:00 2692 Query show create table `sbtest1`
2023-07-11T16:15:51.543729+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:15:51.543837+08:00 2692 Query show fields from `sbtest1`
2023-07-11T16:15:51.544172+08:00 2692 Query show fields from `sbtest1`
2023-07-11T16:15:51.544477+08:00 2692 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `sbtest1`
2023-07-11T16:15:57.603435+08:00 2683 Query insert into testdb_myisam.`sbtest2`(k,c,pad) values(2,'myisam','myisam')
2023-07-11T16:16:27.456357+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:16:27.471239+08:00 2692 Query use `testdb_innodb`
2023-07-11T16:16:27.471589+08:00 2692 Query select @@collation_database
2023-07-11T16:16:27.472065+08:00 2692 Query SHOW TRIGGERS LIKE 'sbtest1'
2023-07-11T16:16:27.506025+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:16:27.506225+08:00 2692 Query ROLLBACK TO SAVEPOINT sp
2023-07-11T16:16:27.506383+08:00 2692 Query RELEASE SAVEPOINT sp
2023-07-11T16:16:27.506538+08:00 2692 Query show events
2023-07-11T16:16:27.507226+08:00 2692 Query use `testdb_innodb`
2023-07-11T16:16:27.507346+08:00 2692 Query select @@collation_database
2023-07-11T16:16:27.507457+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:16:27.507629+08:00 2692 Query SHOW FUNCTION STATUS WHERE Db = 'testdb_innodb'
2023-07-11T16:16:27.621194+08:00 2692 Query SHOW PROCEDURE STATUS WHERE Db = 'testdb_innodb'
2023-07-11T16:16:27.622726+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:16:27.622900+08:00 2692 Init DB testdb_myisam
2023-07-11T16:16:27.623005+08:00 2692 Query SHOW CREATE DATABASE IF NOT EXISTS `testdb_myisam`
2023-07-11T16:16:27.623102+08:00 2692 Query SAVEPOINT sp
2023-07-11T16:16:27.623211+08:00 2692 Query show tables
2023-07-11T16:16:27.623566+08:00 2692 Query show table status like 'sbtest2'
2023-07-11T16:16:27.624197+08:00 2692 Query SET SQL_QUOTE_SHOW_CREATE=1
2023-07-11T16:16:27.624314+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:16:27.624401+08:00 2692 Query show create table `sbtest2`
2023-07-11T16:16:27.624518+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:16:27.624605+08:00 2692 Query show fields from `sbtest2`
2023-07-11T16:16:27.625027+08:00 2692 Query show fields from `sbtest2`
2023-07-11T16:16:27.625391+08:00 2692 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `sbtest2`
2023-07-11T16:16:27.636073+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:16:27.636213+08:00 2692 Query use `testdb_myisam`
2023-07-11T16:16:27.636317+08:00 2692 Query select @@collation_database
2023-07-11T16:16:27.636429+08:00 2692 Query SHOW TRIGGERS LIKE 'sbtest2'
2023-07-11T16:16:27.636923+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:16:27.637034+08:00 2692 Query ROLLBACK TO SAVEPOINT sp
2023-07-11T16:16:27.637116+08:00 2692 Query RELEASE SAVEPOINT sp
2023-07-11T16:16:27.637195+08:00 2692 Query show events
2023-07-11T16:16:27.637517+08:00 2692 Query use `testdb_myisam`
2023-07-11T16:16:27.637631+08:00 2692 Query select @@collation_database
2023-07-11T16:16:27.637741+08:00 2692 Query SET SESSION character_set_results = 'binary'
2023-07-11T16:16:27.637839+08:00 2692 Query SHOW FUNCTION STATUS WHERE Db = 'testdb_myisam'
2023-07-11T16:16:27.639206+08:00 2692 Query SHOW PROCEDURE STATUS WHERE Db = 'testdb_myisam'
2023-07-11T16:16:27.640377+08:00 2692 Query SET SESSION character_set_results = 'utf8'
2023-07-11T16:16:27.663274+08:00 2692 Quit
スレーブ サーバー上で、上記の mysqldump 論理バックアップ ファイルを使用してリカバリを実行し、スレーブ ライブラリを構築します。
-- 从库查看数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
-- 清空从库 binlog 和 gtid 信息
mysql> reset master;
-- 查看确认
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
-- 执行 mysqldump 逻辑备份文件恢复
mysql> source /tmp/dump.sql;
-- 建立复制,并启动复制
mysql> change master to MASTER_HOST='10.186.60.187',MASTER_PORT=3307,master_user='repl',master_password='1',MASTER_AUTO_POSITION=1;
mysql> start slave;
-- 查看复制状态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.186.60.187
Master_User: repl
Master_Port: 3307
Connect_Retry: 60
Master_Log_File: mysql-bin.000015
Read_Master_Log_Pos: 190088135
Relay_Log_File: mysql-relay.000002
Relay_Log_Pos: 414
Relay_Master_Log_File: mysql-bin.000015
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '19112042-1f97-11ee-bf09-02000aba3cbb:3747' at master log mysql-bin.000015, end_log_pos 190087781. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
Skip_Counter: 0
Exec_Master_Log_Pos: 190087413
Relay_Log_Space: 1339
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1062
Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '19112042-1f97-11ee-bf09-02000aba3cbb:3747' at master log mysql-bin.000015, end_log_pos 190087781. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
Replicate_Ignore_Server_Ids:
Master_Server_Id: 629181509
Master_UUID: 19112042-1f97-11ee-bf09-02000aba3cbb
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 230711 17:03:01
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 19112042-1f97-11ee-bf09-02000aba3cbb:3747-3748
Executed_Gtid_Set: 19112042-1f97-11ee-bf09-02000aba3cbb:1-3746
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
-- 查看复制具体报错内容
mysql> select * from performance_schema.replication_applier_status_by_worker\G;
*************************** 1. row ***************************
CHANNEL_NAME:
WORKER_ID: 1
THREAD_ID: NULL
SERVICE_STATE: OFF
LAST_SEEN_TRANSACTION: 19112042-1f97-11ee-bf09-02000aba3cbb:3747
LAST_ERROR_NUMBER: 1062
LAST_ERROR_MESSAGE: Worker 1 failed executing transaction '19112042-1f97-11ee-bf09-02000aba3cbb:3747' at master log mysql-bin.000015, end_log_pos 190087781; Could not execute Write_rows event on table testdb_myisam.sbtest2; Duplicate entry '2' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 190087781
LAST_ERROR_TIMESTAMP: 2023-07-11 17:03:01
原理分析
- mysqldump がバックアップを開始し、整合性ポイントを取得すると、それがT1時間
UNLOCK TABLES
として記録されます。 - InnoDB テーブルのバックアップが完了します (InnoDB テーブルが最初にバックアップされると仮定します)。これはT2時間として記録されます。
- MyISAM エンジン テーブルのバックアップが完了し、時刻T3として記録されます。
- T1とT2の間で、MyISAM エンジン テーブルで INSERT 操作がある場合、binlog が生成され、mysqldump はT1とT2の間の MyISAM エンジン テーブルの INSERT データもバックアップします。
- このようにして、レプリケーションの開始後、SQL スレッドはT1からT2までのバイナリログを再生し、データのこの部分はすでにバックアップ ファイル内にあり、スレーブ ライブラリに復元されているため、SQL スレッドの再生では重複キーが報告されます。
- このオプションを使用する場合:一貫性のあるバックアップの取得は InnoDB エンジンにのみ適用されます。InnoDB エンジン テーブル バックアップの場合は、 T1
mysqldump --single-transaction
でのスナップショットが取得されます。InnoDB エンジン以外のテーブル バックアップの場合は、現在の最新データが取得されます。
改善のための提案
-
業務データベースの非InnoDBエンジンテーブルをInnoDBに変更し、再度バックアップ後にスレーブデータベースを構築します(テーブルのストレージエンジンの変更にはコストがかかり、ストレージエンジンの変更によるオンライン業務への影響も考慮する必要があるため、テーブルをInnoDBエンジンに変更できる場合に適しています)。
-
代わりに、Xtrabackup バックアップ ユーティリティを使用してください。InnoDB 以外のテーブルが比較的大きい場合、MyISAM エンジンのバックアップ中に、バックアップ スレッドがインスタンスのグローバル読み取りロック (FLUSH TABLES WITH READ LOCK) を保持する時間が増加し、データベースの可用性に影響を与えるため、業務時間の短い時間帯に実行する必要があります。(テーブル ストレージ エンジンを短期間に変更できない状況に適しています)。
さらに技術的な記事については、https: //opensource.actionsky.com/をご覧ください。
SQLEについて
Akson オープン ソース コミュニティの SQLE は、データベース ユーザーおよび管理者向けの SQL 監査ツールです。これは、マルチシナリオ監査をサポートし、標準化されたオンライン プロセスをサポートし、MySQL 監査をネイティブにサポートし、スケーラブルなデータベース タイプを備えています。
SQL取得
タイプ | 住所 |
---|---|
リポジトリ | https://github.com/actiontech/sqle |
書類 | https://actiontech.github.io/sqle-docs/ |
リリースニュース | https://github.com/actiontech/sqle/releases |
データ監査プラグイン開発ドキュメント | https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse |