mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Bug#34306: Can't make copy of log tables when server binary log is enabled
The problem is that when statement-based replication was enabled, statements such as INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need to grab a read lock on the source table that does not permit concurrent inserts, which would in turn be denied if the source table is a log table because log tables can't be locked exclusively. The solution is to not take such a lock when the source table is a log table as it is unsafe to replicate log tables under statement based replication. Furthermore, the read lock that does not permits concurrent inserts is now only taken if statement-based replication is enabled and if the source table is not a log table.
This commit is contained in:
@@ -832,6 +832,35 @@ Execute select '000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 0
|
||||
Query set global general_log = off
|
||||
deallocate prepare long_query;
|
||||
set global general_log = @old_general_log_state;
|
||||
DROP TABLE IF EXISTS log_count;
|
||||
DROP TABLE IF EXISTS slow_log_copy;
|
||||
DROP TABLE IF EXISTS general_log_copy;
|
||||
CREATE TABLE log_count (count BIGINT(21));
|
||||
SET @old_general_log_state = @@global.general_log;
|
||||
SET @old_slow_log_state = @@global.slow_query_log;
|
||||
SET GLOBAL general_log = ON;
|
||||
SET GLOBAL slow_query_log = ON;
|
||||
CREATE TABLE slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.slow_log));
|
||||
DROP TABLE slow_log_copy;
|
||||
CREATE TABLE general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log));
|
||||
DROP TABLE general_log_copy;
|
||||
SET GLOBAL general_log = OFF;
|
||||
SET GLOBAL slow_query_log = OFF;
|
||||
CREATE TABLE slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.slow_log));
|
||||
DROP TABLE slow_log_copy;
|
||||
CREATE TABLE general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log));
|
||||
DROP TABLE general_log_copy;
|
||||
SET GLOBAL general_log = @old_general_log_state;
|
||||
SET GLOBAL slow_query_log = @old_slow_log_state;
|
||||
DROP TABLE log_count;
|
||||
SET @old_slow_log_state = @@global.slow_query_log;
|
||||
SET SESSION long_query_time = 0;
|
||||
SET GLOBAL slow_query_log = ON;
|
||||
|
||||
71
mysql-test/suite/binlog/r/binlog_stm_row.result
Normal file
71
mysql-test/suite/binlog/r/binlog_stm_row.result
Normal file
@@ -0,0 +1,71 @@
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
SET GLOBAL BINLOG_FORMAT = STATEMENT;
|
||||
SET SESSION BINLOG_FORMAT = STATEMENT;
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
select @@SESSION.BINLOG_FORMAT;
|
||||
@@SESSION.BINLOG_FORMAT
|
||||
STATEMENT
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
#
|
||||
# Ensure that INSERT INTO .. SELECT FROM under SBR takes a read
|
||||
# lock that will prevent the source table from being modified.
|
||||
#
|
||||
# con1
|
||||
SELECT GET_LOCK('Bug#34306', 120);
|
||||
GET_LOCK('Bug#34306', 120)
|
||||
1
|
||||
# con2
|
||||
PREPARE stmt FROM "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
|
||||
EXECUTE stmt;;
|
||||
# default
|
||||
INSERT INTO t2 VALUES (3);;
|
||||
# con1
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
RELEASE_LOCK('Bug#34306')
|
||||
1
|
||||
# con2
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
RELEASE_LOCK('Bug#34306')
|
||||
1
|
||||
# default
|
||||
#
|
||||
# Ensure that INSERT INTO .. SELECT FROM prepared under SBR does
|
||||
# not prevent the source table from being modified if under RBR.
|
||||
#
|
||||
# con2
|
||||
SET SESSION BINLOG_FORMAT = ROW;
|
||||
# con1
|
||||
SELECT GET_LOCK('Bug#34306', 120);
|
||||
GET_LOCK('Bug#34306', 120)
|
||||
1
|
||||
# con2
|
||||
EXECUTE stmt;;
|
||||
# default
|
||||
# con1
|
||||
INSERT INTO t2 VALUES (4);
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
RELEASE_LOCK('Bug#34306')
|
||||
1
|
||||
# con2
|
||||
# default
|
||||
# Show binlog events
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t2
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT)
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 LIKE t1
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES(1)
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES(2)
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (3)
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (4)
|
||||
master-bin.000001 # Query # # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # use `test`; COMMIT
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
107
mysql-test/suite/binlog/t/binlog_stm_row.test
Normal file
107
mysql-test/suite/binlog/t/binlog_stm_row.test
Normal file
@@ -0,0 +1,107 @@
|
||||
--source include/have_log_bin.inc
|
||||
--source include/have_binlog_format_row_or_statement.inc
|
||||
|
||||
# Get rid of previous tests binlog
|
||||
--disable_query_log
|
||||
reset master;
|
||||
--enable_query_log
|
||||
|
||||
#
|
||||
# Bug#34306: Can't make copy of log tables when server binary log is enabled
|
||||
#
|
||||
# This is an additional test for Bug#34306 in order to ensure that INSERT INTO
|
||||
# .. SELECT FROM is properly replicated under SBR and RBR and that the proper
|
||||
# read lock type are acquired.
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
--enable_warnings
|
||||
|
||||
SET GLOBAL BINLOG_FORMAT = STATEMENT;
|
||||
SET SESSION BINLOG_FORMAT = STATEMENT;
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
select @@SESSION.BINLOG_FORMAT;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
|
||||
--connect(con1,localhost,root,,)
|
||||
--connect(con2,localhost,root,,)
|
||||
|
||||
--echo #
|
||||
--echo # Ensure that INSERT INTO .. SELECT FROM under SBR takes a read
|
||||
--echo # lock that will prevent the source table from being modified.
|
||||
--echo #
|
||||
|
||||
--connection con1
|
||||
--echo # con1
|
||||
SELECT GET_LOCK('Bug#34306', 120);
|
||||
--connection con2
|
||||
--echo # con2
|
||||
PREPARE stmt FROM "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
|
||||
--send EXECUTE stmt;
|
||||
--connection default
|
||||
--echo # default
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
||||
state = "User lock" AND
|
||||
info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
|
||||
--source include/wait_condition.inc
|
||||
--send INSERT INTO t2 VALUES (3);
|
||||
--connection con1
|
||||
--echo # con1
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
||||
state = "Locked" and info = "INSERT INTO t2 VALUES (3)";
|
||||
--source include/wait_condition.inc
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
--connection con2
|
||||
--echo # con2
|
||||
--reap
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
--connection default
|
||||
--echo # default
|
||||
--reap
|
||||
|
||||
--echo #
|
||||
--echo # Ensure that INSERT INTO .. SELECT FROM prepared under SBR does
|
||||
--echo # not prevent the source table from being modified if under RBR.
|
||||
--echo #
|
||||
|
||||
--connection con2
|
||||
--echo # con2
|
||||
SET SESSION BINLOG_FORMAT = ROW;
|
||||
--connection con1
|
||||
--echo # con1
|
||||
SELECT GET_LOCK('Bug#34306', 120);
|
||||
--connection con2
|
||||
--echo # con2
|
||||
--send EXECUTE stmt;
|
||||
--connection default
|
||||
--echo # default
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
||||
state = "User lock" AND
|
||||
info = "INSERT INTO t1 SELECT * FROM t2 WHERE GET_LOCK('Bug#34306', 120)";
|
||||
--source include/wait_condition.inc
|
||||
--connection con1
|
||||
--echo # con1
|
||||
INSERT INTO t2 VALUES (4);
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
--connection con2
|
||||
--echo # con2
|
||||
--reap
|
||||
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
--connection default
|
||||
--echo # default
|
||||
|
||||
--echo # Show binlog events
|
||||
source include/show_binlog_events.inc;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
@@ -936,6 +936,52 @@ select command_type, argument from mysql.general_log where thread_id = @thread_i
|
||||
deallocate prepare long_query;
|
||||
set global general_log = @old_general_log_state;
|
||||
|
||||
#
|
||||
# Bug#34306: Can't make copy of log tables when server binary log is enabled
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS log_count;
|
||||
DROP TABLE IF EXISTS slow_log_copy;
|
||||
DROP TABLE IF EXISTS general_log_copy;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE log_count (count BIGINT(21));
|
||||
|
||||
SET @old_general_log_state = @@global.general_log;
|
||||
SET @old_slow_log_state = @@global.slow_query_log;
|
||||
|
||||
SET GLOBAL general_log = ON;
|
||||
SET GLOBAL slow_query_log = ON;
|
||||
|
||||
CREATE TABLE slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.slow_log));
|
||||
DROP TABLE slow_log_copy;
|
||||
|
||||
CREATE TABLE general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log));
|
||||
DROP TABLE general_log_copy;
|
||||
|
||||
SET GLOBAL general_log = OFF;
|
||||
SET GLOBAL slow_query_log = OFF;
|
||||
|
||||
CREATE TABLE slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO slow_log_copy SELECT * FROM mysql.slow_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.slow_log));
|
||||
DROP TABLE slow_log_copy;
|
||||
|
||||
CREATE TABLE general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO general_log_copy SELECT * FROM mysql.general_log;
|
||||
INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log));
|
||||
DROP TABLE general_log_copy;
|
||||
|
||||
SET GLOBAL general_log = @old_general_log_state;
|
||||
SET GLOBAL slow_query_log = @old_slow_log_state;
|
||||
|
||||
DROP TABLE log_count;
|
||||
|
||||
#
|
||||
# Bug #31700: thd->examined_row_count not incremented for 'const' type queries
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user