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_
を使用する際はご注意ください。