MySQL データ送信パラメータ設定がデータの一貫性に及ぼす影響

著者は、包括的かつ体系的なテストを通じて、 lower_case_table_names 設定がデータの一貫性に及ぼす影響を明らかにしました。

著者: リウ・アン

Acson のテスト チームのメンバーで、主に DTLE オープン ソース プロジェクトに関連するテスト タスクを担当しており、Python 自動テスト開発を得意としています。

この記事の出典: 元の寄稿

  • Aikesheng オープンソース コミュニティによって作成されており、オリジナルのコンテンツを許可なく使用することはできません。転載する場合は編集者に連絡し、出典を明示してください。

バックグラウンド

最近、お客様から「ソース MySQL とターゲット MySQLlower_case_table_namesの構成が一致していない場合、DTLE はデータを正常に同期できますか?」という質問がありました。

この記事では、lower_case_table_namesこの問題に対する DTLE 同期データの設定の影響をテストします。

シナリオを簡略化するために、ここではLinux 環境でのまたはlower_case_table_namesの構成についてのみ説明します01

環境整備

  1. DTLE 4.23.04.2 のデプロイ
  2. lower_case_table_names構成が異なる 2 つの MySQL インスタンス
# lower_case_table_names=0
$ dbdeployer deploy single 5.7 --port 3306 --sandbox-directory sandbox --port-as-server-id --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON --gtid -c lower_case_table_names=0

# lower_case_table_names=1
$ dbdeployer deploy single 5.7 --port 3306 --sandbox-directory sandbox --port-as-server-id --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON --gtid -c lower_case_table_names=1

最初のケース

  • ソースMySQL@@lctn=0
  • ターゲットMySQL@@lctn=1

DTLE の開発ドキュメントによると、この場合の DTLE の動作は次のとおりです。

  • オリジンは元のケースで実行されます。
  • ターゲット側は BinlogEntry を受け取ります。DML/DDL は元の大文字で実行され、MySQL によって自動的に小文字に変換されます。

以下は、いくつかの一般的な SQL を実行した場合のデータ同期結果です。

ソース SQL とデータ ターゲットセグメントデータ
データベースアクション_DBを作成します。

mysql> SHOW DATABASES\G
** 1.行**
データベース: ACTION_DB
mysql> SHOW DATABASES\G
** 1. 行**
データベース: action_db
** 2. 行**
データベース: dtle
CREATE TABLE ACTION_DB.A(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> SHOW TABLES\G
** 1. 行**
Tables_in_ACTION_DB: A
mysql> SHOW TABLES\G
** 1. 行**
Tables_in_action_db: a
ACTION_DB.A 値に挿入 (1);

mysql> SELECT * FROM ACTION_DB.A\G
** 1.行**
ID: 1
mysql> SELECT * FROM ACTION_DB.A\G
** 1.行**
ID: 1
ALTER TABLE ACTION_DB.A ADD D CHAR(20);

mysql> SHOW CREATE TABLE ACTION_DB.A\G
** 1. row **
テーブル: A

テーブルの作成: CREATE TABLE `A` (
`id` int(11) DEFAULT NULL,
`D` char(20) DEFAULT NULL
) ENGINE =InnoDB デフォルト文字セット=utf8
mysql> SHOW CREATE TABLE ACTION_DB.A\G
** 1. row **
テーブル: A

テーブルの作成: CREATE TABLE `a` (
`id` int(11) DEFAULT NULL,
`D` char(20) DEFAULT NULL
) ENGINE =InnoDB デフォルト文字セット=utf8
ALTER TABLE ACTION_DB.A RENAME TO ACTION_DB.B;

mysql> SHOW TABLES\G
** 1. 行**
Tables_in_ACTION_DB: B
mysql> SHOW TABLES\G
** 1. 行**
Tables_in_action_db: b
ドロップテーブルアクション_DB.B;

mysql> SHOW TABLES\G
空のセット (0.00 秒)
mysql> SHOW TABLES\G
空のセット (0.00 秒)

DTLE 同期後のデータは期待どおりであることがわかります。ソース側の MySQL の大文字と小文字は SQL と同じであり、ターゲット側の MySQL は自動的に小文字に変換されます。


いくつかの極端なケースを見てみましょう。

ソース側の SQL とデータ 対象データ
データベースアクション_DBを作成します。

mysql> SHOW DATABASES\G
** 1.行**
データベース: ACTION_DB
mysql> SHOW DATABASES\G
** 1. 行**
データベース: action_db
** 2. 行**
データベース: dtle
CREATE DATABASE action_db;

mysql> SHOW DATABASES\G
** 1. row **
Database: ACTION_DB
** 2. row **
Database: action_db
mysql> SHOW DATABASES\G
** 1. row **
Database: action_db
** 2. row **
Database: dtle
CREATE TABLE ACTION_DB.A(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> use ACTION_DB
mysql> SHOW TABLES\G
** 1. row **
Tables_in_ACTION_DB: A
mysql> use action_db
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
CREATE TABLE ACTION_DB.a(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> use ACTION_DB
mysql> SHOW TABLES\G
** 1. row **
Tables_in_ACTION_DB: A
** 2. row **
Tables_in_ACTION_DB: a
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
CREATE TABLE action_db.A(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> USE action_db
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: A
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
CREATE TABLE action_db.a(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> USE action_db
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: A
** 2. row **
Tables_in_action_db: a
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
INSERT INTO ACTION_DB.A VALUES (1);

mysql> SELECT * FROM ACTION_DB.A\G
** 1. row **
id: 1
mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 1
INSERT INTO ACTION_DB.a VALUES (2);

mysql> SELECT * FROM ACTION_DB.a\G
** 1. row **
id: 2
mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 1
** 2. row **
id: 2
INSERT INTO action_db.A VALUES (3);

mysql> SELECT * FROM action_db.A\G
** 1. row **
id: 3
mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 1
** 2. row **
id: 2
** 3. row **
id: 3
INSERT INTO action_db.a VALUES (4);

mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 4
mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 1
** 2. row **
id: 2
** 3. row **
id: 3
** 4. row **
id: 4

可以看到此时 DTLE 的行为,相当于把 ACTION_DB.AACTION_DB.aaction_db.Aaction_db.a 四个表的数据合并到一张表。

所以为了避免此种情况,可以通过在创建 DTLE 作业的时候,为每个重名的库配置 TableSchemaRename 属性、重名表配置 Table.TableRename 属性的方式来解决。

第二种情况

  • 源端 MySQL @@lctn=1
  • 目标端MySQL @@lctn=0

根据 DTLE 的开发文档 里面介绍,此种情况下的 DTLE 行为:

  • 用户填写的复制范围,应转化为小写。
  • 不复制已有的大写 SCHEMA.TABLE
  • 新增的 Schema.Table,转化为小写后,加入复制范围。
  • 目标端无论 @@lctn=0@@lctn=1,都应该复制源端的效果,即小写。
  • 目标端收到的 BinlogEntry 中,schema.tableName 已为小写。

以下是执行一些典型 SQL 的数据同步结果:

源端 SQL 和数据 目标端数据
CREATE DATABASE ACTION_DB;

mysql> SHOW DATABASES\G
** 1. row **
Database: action_db
mysql> SHOW DATABASES\G
** 1. row **
Database: action_db
** 2. row **
Database: dtle
CREATE TABLE ACTION_DB.A(id int(11))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: a
INSERT INTO ACTION_DB.A VALUES (1);

mysql> SELECT * FROM ACTION_DB.A\G
** 1. row **
id: 1
mysql> SELECT * FROM action_db.a\G
** 1. row **
id: 1
ALTER TABLE ACTION_DB.A ADD D CHAR(20);

mysql> SHOW CREATE TABLE ACTION_DB.A\G
** 1. row **
Table: A

Create Table: CREATE TABLE `a` (
`id` int(11) DEFAULT NULL,
`D` char(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
mysql> SHOW CREATE TABLE action_db.a\G
** 1. row **
Table: a

Create Table: CREATE TABLE `a` (
id int(11) DEFAULT NULL,
`D` char(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
ALTER TABLE ACTION_DB.A RENAME TO ACTION_DB.B;

mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: b
mysql> SHOW TABLES\G
** 1. row **
Tables_in_action_db: b
DROP TABLE ACTION_DB.B;

mysql> SHOW TABLES\G
Empty set (0.00 sec)
mysql> SHOW TABLES\G
Empty set (0.00 sec)

可以看到 DTLE 同步后的数据是符合预期。在源端 MySQL 自动转为小写,在目标端 MySQL 同步的数据也是小写的。

其他限制

通过观察 general log 可以得知,DTLE 作业是在初始化作业的时候获取源端以及目标端 MySQL 的 lower_case_table_names 配置的,所以在 DTLE 作业存续期间更改 MySQL 的该参数是 DTLE 无法感知并处理的。因此禁止在 DTLE 作业存续期间更改此配置。

总结

  1. 原则上 DTLE 还是建议源端和目标端设置相同。
  2. 当源端 MySQL @@lctn=0 且目标端 MySQL @@lctn=1 时,需要注意源端仅大小写不同的同名库表在目标端会汇聚到同一个表中的问题。
  3. DTLE 作业存续期间,MySQL 上的 lower_case_table_names 配置不可改变。

关于 SQLE

爱可生开源社区的 SQLE 是一款面向数据库使用者和管理者,支持多场景审核,支持标准化上线流程,原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。

SQLE 获取

类型 地址
版本库 https://github.com/actiontech/sqle
文档 https://actiontech.github.io/sqle-docs/
发布信息 https://github.com/actiontech/sqle/releases
データ監査プラグイン開発ドキュメント https://actiontech.github.io/sqle-docs-cn/3.modules/3.7_auditplugin/auditplugin_development.html

おすすめ

転載: blog.csdn.net/ActionTech/article/details/131580202