Description:
If you want to change the tx-isolation on a session that already executed a transaction the change is not honored so it may cause a failure in the service.
Example:
[root@data1 yum.repos.d]# mysql -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.33-log MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use percona
Database changed
mysql> show create table checksums\G
*************************** 1. row ***************************
Table: checksums
Create Table: CREATE TABLE `checksums` (
`db` char(64) COLLATE utf8_unicode_ci NOT NULL,
`tbl` char(64) COLLATE utf8_unicode_ci NOT NULL,
`chunk` int(11) NOT NULL,
`chunk_time` float DEFAULT NULL,
`chunk_index` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
`lower_boundary` blob,
`upper_boundary` blob,
`this_crc` char(40) COLLATE utf8_unicode_ci NOT NULL,
`this_cnt` int(11) NOT NULL,
`master_crc` char(40) COLLATE utf8_unicode_ci DEFAULT NULL,
`master_cnt` int(11) DEFAULT NULL,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`db`,`tbl`,`chunk`),
KEY `ts_db_tbl` (`ts`,`db`,`tbl`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
1 row in set (0.00 sec)
mysql> use db_test_tx_iso
Database changed
mysql> show create table test_tx_iso\G
*************************** 1. row ***************************
Table: test_tx_iso
Create Table: CREATE TABLE `test_tx_iso` (
`key` varbinary(742) NOT NULL,
`version` bigint(20) NOT NULL,
`value` mediumblob,
`pelock` varbinary(64) DEFAULT NULL,
PRIMARY KEY (`key`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4
1 row in set (0.00 sec)
mysql> show global variables like 'binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.01 sec)
mysql> show global variables like 'tx_isolatio%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.01 sec)
mysql> show variables like 'tx_isolatio%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.10 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`;
Query OK, 2 rows affected (0.24 sec)
Records: 1 Duplicates: 1 Warnings: 0
*works ok, tx-isolation is read-commited and binlog-format=row
*now within same session:
mysql> set session tx_isolation="REPEATABLE-READ"; set session binlog_format=STATEMENT; REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`;
Query OK, 0 rows affected, 1 warning (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
mysql> show variables like 'tx_isolatio%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.01 sec)
*Query fails even if session changed tx-isolation to REPEATABLE-READ
Now if I start a new session:
[root@data1 yum.repos.d]# mysql -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.33-log MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show variables like 'tx_isolatio%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.00 sec)
mysql> set session tx_isolation="REPEATABLE-READ"; set session binlog_format=STATEMENT; REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 2 rows affected, 1 warning (0.05 sec)
Records: 1 Duplicates: 1 Warnings: 1
mysql> REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`;
Query OK, 2 rows affected, 1 warning (0.01 sec)
Records: 1 Duplicates: 1 Warnings: 1
Queries are executed in the expected way
How to repeat:
1- Start server with binlog_format=ROW and transaction_isolation=READ-COMMITTED
2- create 2 tables, no need to add data or specific table format.
3- Run a REPLACE INTO table1 SELECT FROM table2; command
4- Change tx-isolation to REPEATABLE READ and binlog_format to STATEMENT (pretty much what pt-table-checksum needs to do)
5- Repeat query from step 3, it should fail.
Suggested fix:
This looks like a regression as is not reproducible in 5.7.29, nor in 5.6 versions.
Expected behavior is that if change of tx-isolation is done on a running session the transaction honor the change and behave accordingly as it was working up to 5.7.29
Description: If you want to change the tx-isolation on a session that already executed a transaction the change is not honored so it may cause a failure in the service. Example: [root@data1 yum.repos.d]# mysql -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.33-log MySQL Community Server (GPL) Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use percona Database changed mysql> show create table checksums\G *************************** 1. row *************************** Table: checksums Create Table: CREATE TABLE `checksums` ( `db` char(64) COLLATE utf8_unicode_ci NOT NULL, `tbl` char(64) COLLATE utf8_unicode_ci NOT NULL, `chunk` int(11) NOT NULL, `chunk_time` float DEFAULT NULL, `chunk_index` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, `lower_boundary` blob, `upper_boundary` blob, `this_crc` char(40) COLLATE utf8_unicode_ci NOT NULL, `this_cnt` int(11) NOT NULL, `master_crc` char(40) COLLATE utf8_unicode_ci DEFAULT NULL, `master_cnt` int(11) DEFAULT NULL, `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`db`,`tbl`,`chunk`), KEY `ts_db_tbl` (`ts`,`db`,`tbl`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 1 row in set (0.00 sec) mysql> use db_test_tx_iso Database changed mysql> show create table test_tx_iso\G *************************** 1. row *************************** Table: test_tx_iso Create Table: CREATE TABLE `test_tx_iso` ( `key` varbinary(742) NOT NULL, `version` bigint(20) NOT NULL, `value` mediumblob, `pelock` varbinary(64) DEFAULT NULL, PRIMARY KEY (`key`,`version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 1 row in set (0.00 sec) mysql> show global variables like 'binlog_format%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | binlog_format | ROW | +---------------+-------+ 1 row in set (0.01 sec) mysql> show global variables like 'tx_isolatio%'; +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | tx_isolation | READ-COMMITTED | +---------------+----------------+ 1 row in set (0.01 sec) mysql> show variables like 'tx_isolatio%'; +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | tx_isolation | READ-COMMITTED | +---------------+----------------+ 1 row in set (0.10 sec) mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec) mysql> REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`; Query OK, 2 rows affected (0.24 sec) Records: 1 Duplicates: 1 Warnings: 0 *works ok, tx-isolation is read-commited and binlog-format=row *now within same session: mysql> set session tx_isolation="REPEATABLE-READ"; set session binlog_format=STATEMENT; REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`; Query OK, 0 rows affected, 1 warning (0.01 sec) Query OK, 0 rows affected (0.00 sec) ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. mysql> show variables like 'tx_isolatio%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+ 1 row in set (0.01 sec) *Query fails even if session changed tx-isolation to REPEATABLE-READ Now if I start a new session: [root@data1 yum.repos.d]# mysql -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 Server version: 5.7.33-log MySQL Community Server (GPL) Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'tx_isolatio%'; +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | tx_isolation | READ-COMMITTED | +---------------+----------------+ 1 row in set (0.00 sec) mysql> set session tx_isolation="REPEATABLE-READ"; set session binlog_format=STATEMENT; REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`; Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 2 rows affected, 1 warning (0.05 sec) Records: 1 Duplicates: 1 Warnings: 1 mysql> REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'db_test_tx_iso', 'test_tx_iso', 1, null, null, null, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', CRC32(`key`), `version`, CRC32(`value`), CRC32(`pelock`), CONCAT(ISNULL(`value`), ISNULL(`pelock`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `db_test_tx_iso`.`test_tx_iso`; Query OK, 2 rows affected, 1 warning (0.01 sec) Records: 1 Duplicates: 1 Warnings: 1 Queries are executed in the expected way How to repeat: 1- Start server with binlog_format=ROW and transaction_isolation=READ-COMMITTED 2- create 2 tables, no need to add data or specific table format. 3- Run a REPLACE INTO table1 SELECT FROM table2; command 4- Change tx-isolation to REPEATABLE READ and binlog_format to STATEMENT (pretty much what pt-table-checksum needs to do) 5- Repeat query from step 3, it should fail. Suggested fix: This looks like a regression as is not reproducible in 5.7.29, nor in 5.6 versions. Expected behavior is that if change of tx-isolation is done on a running session the transaction honor the change and behave accordingly as it was working up to 5.7.29