MySQL 5.binlog_オプションのデフォルトがROWになりました。MySQL5.
今回は、slave_オプションによるカラムのデータ型の異なるRBRの挙動について紹介します。
slave_type_conversionsオプションとは
このオプションはRBRを使用するときにスレーブに対して設定するもので、
では、
マスターの設定
RBRの設定であることを確認します。
mysql> select @@binlog_format; +-----------------+ | @@binlog_format | +-----------------+ | ROW | +-----------------+
スレーブの設定
slave_がデフォルトの''
mysql> select @@slave_type_conversions; +--------------------------+ | @@slave_type_conversions | +--------------------------+ | | +--------------------------+
マスターでt0テーブルを作成
mysql> CREATE TABLE `t0` ( `id` int(11) NOT NULL AUTO_INCREMENT, `col` varchar(5) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
スレーブでカラムcolのvarchar(5) から varchar(10)に変更
mysql> alter table t0 modify col varchar(10);
これで、colの型はvarchar(5)でスレーブのカラムcolの型はvarchar(10)という状態になります。ここでマスターで更新すると、
マスターで更新
mysql> insert into t0(col) values ('ABCDE');
スレーブでレプリケーションエラー
Last_SQL_Error: Column 1 of table 'aa.t0' cannot be converted from type 'varchar(5)' to type 'varchar(10)'
slave_オプションにモードを設定することでこれを回避することができます。有効なモードは以下のようになります。
| モード | 内容 | 有効なバージョン |
|---|---|---|
| ALL_ | 不可逆変換を許可します | MySQL5. |
| ALL_ | 非不可逆変換を許可します | MySQL5. |
| ALL_ | 昇格される整数型を符号付き値として扱います | MySQL5. |
| ALL_ | 昇格される整数型を符号なし値として扱います | MySQL5. |
| ''(空文字) | すべての変換を許可しません | MySQL5. |
このオプションは動的に変更可能ですが、
以下、
ALL_LOSSY
このモードはスレーブのカラムの型がマスターのカラムの型よりも小さい場合、
たとえば、
ALL_LOSSYの動作
前述で使用したテーブルを使って試してみます。スレーブの型をvarchar(1)に変更しています。
スレーブで設定
mysql> select @@slave_type_conversions; +--------------------------+ | @@slave_type_conversions | +--------------------------+ | ALL_LOSSY | +--------------------------+ mysql> alter table t0 modify col varchar(1); Query OK, 0 rows affected (0.00 sec)
マスターで更新
mysql> insert into t0(col) values ('ABCDE');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t0;
+----+------+
| id | col |
+----+------+
| 1 | ABCDE|
+----+------+
1 rows in set (0.00 sec)
スレーブで確認
mysql> select * from t0; +----+------+ | id | col | +----+------+ | 1 | A | +----+------+ 1 rows in set (0.00 sec)
このように、
ALL_NON_LOSSY
このモードは前述と同様に、
たとえば、
ALL_NON_LOSSYの動作
こちらも前述で使用したテーブルを使って試してみます。スレーブの型をvarchar(200)に変更しています。
スレーブで設定
mysql> select @@slave_type_conversions; +--------------------------+ | @@slave_type_conversions | +--------------------------+ | ALL_NON_LOSSY | +--------------------------+ mysql> alter table t0 modify col varchar(200); Query OK, 0 rows affected (0.00 sec)
マスターで更新
mysql> insert into t0(col) values ('ABCDE');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t0;
+----+------+
| id | col |
+----+------+
| 1 | ABCDE|
+----+------+
1 rows in set (0.00 sec)
スレーブで確認
mysql> select * from t0; +----+------+ | id | col | +----+------+ | 1 | ABCDE| +----+------+ 1 rows in set (0.00 sec)
エラーなく登録されていることがわかります。
以下のようにカンマ区切りで複数のモードを設定することも可能です。
mysql> set global slave_type_conversions='ALL_LOSSY,ALL_NON_LOSSY';
この2つのモード組み合わせると、
また、
ALL_SIGNEDとALL_UNSIGNED
続いて、ALL_は符号付きとして値を扱い、ALL_は符号なしとして値を扱います。指定がない場合はALL_がデフォルトで動作します。前述のALL_、ALL_、
たとえば、
| モード | マスターの値 | スレーブの値 |
|---|---|---|
| ALL_ | -128 | -128 |
| ALL_ | 127 | 127 |
| ALL_ | -128 | 128 |
| ALL_ | 127 | 127 |
このように、ALL_の場合は符号なしとして扱うため、
ちなみに、ALL_、ALL_の順に評価されます。
ALL_LOSSYとSTRICT_TRANS_TABLESの関係
sql_オプションにSTRICT_というモードがあります。これを有効にしていると、ABCという文字列を挿入しようとすると、
mysql> insert into t1 ( strict_col ) values ( 'ABC'); ERROR 1406 (22001): Data too long for column 'strict_col' at row 1
では、STRICT_が有効、ALL_が設定されていて、
答えは、ALL_が優先されて、
ちなみに、slave_オプションはRBRにのみ影響するオプションなので、STRICT_の影響により、
こちらも前述のテーブルを使用して試してみましょう。
スレーブの設定
varchar(2)へ変更します。
mysql> select @@slave_type_conversions; +--------------------------+ | @@slave_type_conversions | +--------------------------+ | ALL_LOSSY | +--------------------------+ mysql> set global sql_mode='STRICT_TRANS_TABLES'; Query OK, 0 rows affected (0.00 sec) mysql> alter table t0 modify col varchar(2); Query OK, 0 rows affected (0.00 sec)
マスターの設定
mysql> select @@binlog_format; +-----------------+ | @@binlog_format | +-----------------+ | ROW | +-----------------+
マスターで更新
mysql> insert into t0(col) values ('ABCDE');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t0;
+----+------+
| id | col |
+----+------+
| 1 | ABCDE|
+----+------+
1 rows in set (0.00 sec)
スレーブで確認
mysql> select * from t0; +----+------+ | id | col | +----+------+ | 1 | AB | +----+------+ 1 rows in set (0.00 sec)
このようにエラーはなく、
続いて、
スレーブの設定
varchar(2)へ変更します。
mysql> select @@slave_type_conversions; +--------------------------+ | @@slave_type_conversions | +--------------------------+ | ALL_LOSSY | +--------------------------+ mysql> set global sql_mode='STRICT_TRANS_TABLES'; Query OK, 0 rows affected (0.00 sec) mysql> alter table t0 modify col varchar(2); Query OK, 0 rows affected (0.00 sec)
マスターの設定
mysql> select @@binlog_format; +-----------------+ | @@binlog_format | +-----------------+ | STATEMENT | +-----------------+
マスターで更新
mysql> insert into t0(col) values ('ABCDE');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t0;
+----+------+
| id | col |
+----+------+
| 1 | ABCDE|
+----+------+
1 rows in set (0.00 sec)
スレーブで確認
mysql> show slave status¥G
Last_Error: Error 'Data too long for column 'col' at row 1' on query. Default database: 'aa'. Query: 'insert into t0(col) values ('ABCDE')'
このように、STRICT_の影響により、
まとめ
今回は、slave_オプションによるテーブル定義の異なるRBRの挙動について紹介しました。これを使用すれば、Alter Table文を、
ただし、ALL_を使用する際はご注意ください。