mirror of
https://github.com/MariaDB/server.git
synced 2025-04-18 05:05:32 +02:00

The purpose of this commit is to ensure that creation and changes of temporary tables are properly and predicable logged to the binary log. It also fixes some bugs where ROW logging was used in MIXED mode, when STATEMENT would be a better (and expected) choice. In this comment STATEMENT stands for logging to binary log in STATEMENT format, MIXED stands for MIXED binlog format and ROW for ROW binlog format. New rules for logging of temporary tables - CREATE of temporary tables are now by default binlogged only if STATEMENT binlog format is used. If it is binlogged, 1 is stored in TABLE_SHARE->table_creation_was_logged. The user can change this behavior by setting create_temporary_table_binlog_formats to MIXED,STATEMENT in which case the create is logged in statement format also in MIXED mode (as before). - Changes to temporary tables are only binlogged if and only if the CREATE was logged. The logging happens under STATEMENT or MIXED. If binlog_format=ROW, temporary table changes are not binlogged. A temporary table that are changed under ROW are marked as 'not up to date in binlog' and no future row changes are logged. Any usage of this temporary table will force row logging of other tables in any future statements using the temporary table to be row logged. - DROP TEMPORARY is binlogged only of the CREATE was binlogged. Changes done: - Row logging is forced for any statement using temporary tables that are not up to date in the binary log. (Before the row logging was forced if the user has a temporary table) - If there is any changes to the temporary table that is not binlogged, the table is marked as not up to date. - TABLE_SHARE->table_creation_was_logged has a new definition for temporary tables: 0 Table creating was not logged to binary log 1 Table creating was logged to binary log and table is up to date. 2 Table creating was logged to binary log but some changes where not logged to binary log. Table is not up to date in binary log is defined as value 0 or 2. - If a multi-table-update or multi-table-delete fails then all updated temporary tables are marked as not up to date. - Enforce row logging if the query is using temporary tables that are not up to date. Before row logging was enforced if the user had any temporary tables. - When dropping temporary tables use IF EXISTS. This ensures that slave will not stop if it had crashed and lost the temporary tables. - Remove comment and version from DROP /*!4000 TEMPORARY.. generated when a connection closes that has open temporary tables. Added 'generated by server' at the end of the DROP. Bugs fixed: - When using temporary tables with commands that forced row based, like INSERT INTO temporary_table VALUES (UUID()), this was never logged which causes the temporary table to be inconsistent on master and slave. - Used binlog format is now clearly defined. It is now only depending on the current binlog_format and the tables used. Before it was depending on the user had ANY temporary tables and the state of 'current_stmt_binlog_format' set by previous queries. This also caused temporary tables to be logged to binary log in some cases. - CREATE TABLE t1 LIKE not_logged_temporary_table caused replication to stop. - Rename of not binlogged temporary tables where binlogged to binary log which caused replication to stop. Changes in behavior: - By default create_temporary_table_binlog_formats=STATEMENT, which means that CREATE TEMPORARY is not logged to binary log under MIXED binary logging. This can be changed by setting create_temporary_table_binlog_formats to MIXED,STATEMENT. - Using temporary tables that was not logged to the binary log will cause any query using them for updating other tables to be logged in ROW format. Before all queries was logged in ROW format if the user had any temporary tables, even if they were not used by the query. - Generated DROP TEMPORARY TABLE is now always using IF EXISTS and has a "generated by server" comment in the binary log. The consequences of the above is that manipulations of a lot of rows through temporary tables will by default be be slower in mixed mode. For example: BEGIN; CREATE TEMPORARY TABLE tmp AS SELECT a, b, c FROM large_table1 JOIN large_table2 ON ...; INSERT INTO other_table SELECT b, c FROM tmp WHERE a <100; DROP TEMPORARY TABLE tmp; COMMIT; By default this will create a huge entry in the binary log, compared to just a few hundred bytes in statement mode. However the change in this commit will make usage of temporary tables more reliable and predicable and is thus worth it. Using statement mode or create_temporary_table_binlog_formats can be used to avoid this issue.
180 lines
5.1 KiB
Text
180 lines
5.1 KiB
Text
--source include/have_innodb.inc
|
|
|
|
--disable_warnings
|
|
DROP DATABASE IF EXISTS `drop-temp+table-test`;
|
|
--enable_warnings
|
|
|
|
select @@session.binlog_format;
|
|
select @@session.create_temporary_table_binlog_formats;
|
|
|
|
connect (con1,localhost,root,,);
|
|
connect (con2,localhost,root,,);
|
|
connection con1;
|
|
RESET MASTER;
|
|
CREATE DATABASE `drop-temp+table-test`;
|
|
USE `drop-temp+table-test`;
|
|
CREATE TEMPORARY TABLE shortn1 (a INT);
|
|
CREATE TEMPORARY TABLE `table:name` (a INT);
|
|
CREATE TEMPORARY TABLE shortn2 (a INT);
|
|
|
|
##############################################################################
|
|
# MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written
|
|
# to binlog only if the corresponding temporary table exists.
|
|
##############################################################################
|
|
CREATE TEMPORARY TABLE tmp(c1 int);
|
|
CREATE TEMPORARY TABLE tmp1(c1 int);
|
|
CREATE TEMPORARY TABLE tmp2(c1 int);
|
|
CREATE TEMPORARY TABLE tmp3(c1 int);
|
|
CREATE TABLE t(c1 int);
|
|
|
|
DROP TEMPORARY TABLE IF EXISTS tmp;
|
|
|
|
--disable_warnings
|
|
# Post MDEV-20091: Following DROP TEMPORARY TABLE statement should not be
|
|
# logged as the table is already dropped above.
|
|
DROP TEMPORARY TABLE IF EXISTS tmp;
|
|
|
|
# Post MDEV-20091: Only DROP TEMPORARY TABLE statement should be written only
|
|
# for 'tmp1' table.
|
|
DROP TEMPORARY TABLE IF EXISTS tmp, tmp1;
|
|
DROP TEMPORARY TABLE tmp3;
|
|
|
|
#In RBR, tmp2 will NOT be binlogged, because it is a temporary table.
|
|
DROP TABLE IF EXISTS tmp2, t;
|
|
|
|
#In RBR, tmp2 will be binlogged, because it does not exist and master do not know
|
|
# whether it is a temporary table or not.
|
|
DROP TABLE IF EXISTS tmp2, t;
|
|
--enable_warnings
|
|
|
|
SELECT GET_LOCK("a",10);
|
|
|
|
#
|
|
# BUG48216 Replication fails on all slaves after upgrade to 5.0.86 on master
|
|
#
|
|
# When the session is closed, any temporary tables of the session are dropped
|
|
# and are binlogged. But it will be binlogged with a wrong database name when
|
|
# the length of the database name('drop-temp-table-test') is greater than the
|
|
# current database name('test').
|
|
#
|
|
USE test;
|
|
disconnect con1;
|
|
|
|
connection con2;
|
|
# We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
|
|
# guarantee that logging of the terminated con1 has been done yet.
|
|
# To be sure that logging has been done, we use a user lock.
|
|
SELECT GET_LOCK("a",10);
|
|
let $VERSION=`SELECT VERSION()`;
|
|
source include/show_binlog_events.inc;
|
|
DROP DATABASE `drop-temp+table-test`;
|
|
|
|
|
|
#
|
|
# Bug #54842: DROP TEMPORARY TABLE not binlogged after manual switching binlog format to ROW
|
|
#
|
|
# Sanity test. Checking that implicit DROP event is logged.
|
|
#
|
|
# After BUG#52616, the switch to ROW mode becomes effective even
|
|
# if there are open temporary tables. As such the implicit drop
|
|
# for temporary tables on session closing must be logged.
|
|
#
|
|
# MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written to
|
|
# binlog only if the corresponding temporary table exists. In row based
|
|
# replication temporary tables are not replicated hence their corresponding
|
|
# DROP TEMPORARY TABLE statement will be not be written to binary log upon
|
|
# session closure.
|
|
#
|
|
|
|
RESET MASTER;
|
|
|
|
CREATE TABLE t1 ( i text );
|
|
|
|
--connect(con1,localhost,root,,)
|
|
CREATE TEMPORARY TABLE ttmp1 ( i text );
|
|
SET @@session.binlog_format=ROW;
|
|
INSERT INTO t1 VALUES ('1');
|
|
SELECT @@session.binlog_format;
|
|
--disconnect con1
|
|
|
|
-- connection default
|
|
if (`SELECT FIND_IN_SET(@@BINLOG_FORMAT,@@CREATE_TEMPORARY_TABLE_BINLOG_FORMATS) > 0`)
|
|
{
|
|
--let $wait_binlog_event= DROP
|
|
--source include/wait_for_binlog_event.inc
|
|
}
|
|
-- source include/show_binlog_events.inc
|
|
RESET MASTER;
|
|
|
|
DROP TABLE t1;
|
|
|
|
# End of 4.1 tests
|
|
|
|
|
|
--echo #
|
|
--echo # BUG#28642318: POINT IN TIME RECOVERY USING MYSQLBINLOG BROKEN
|
|
--echo # WITH TEMPORARY TABLE -> ERRORS
|
|
|
|
--echo # Test case for DELETE query.
|
|
|
|
RESET MASTER;
|
|
connect (con1,localhost,root,,);
|
|
|
|
--echo # Set up.
|
|
--connection default
|
|
--disable_warnings
|
|
SET @save_binlog_format= @@session.binlog_format;
|
|
SET @@session.binlog_format=STATEMENT;
|
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
|
CREATE TABLE t1 (a INT) ENGINE=INNODB;
|
|
|
|
--connection con1
|
|
SET @@session.binlog_format=STATEMENT;
|
|
CREATE TEMPORARY TABLE t1 (b BLOB) ENGINE=INNODB;
|
|
|
|
--connection default
|
|
DELETE d1, d2 FROM t1 AS d1, t1 AS d2 WHERE d1.a<>d2.a;
|
|
|
|
--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/bug28642318.sql
|
|
|
|
--connection default
|
|
DROP TABLE t1;
|
|
|
|
--echo # DELETE query fails with table re-open error without patch.
|
|
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug28642318.sql
|
|
|
|
--echo # Clean up.
|
|
--connection con1
|
|
DROP TABLE IF EXISTS t1;
|
|
|
|
--connection default
|
|
DROP TABLE IF EXISTS t1;
|
|
RESET MASTER;
|
|
|
|
--echo # Test case for DROP query.
|
|
|
|
--connection default
|
|
CREATE TABLE t2 (a INT) ENGINE=INNODB;
|
|
|
|
--connection con1
|
|
CREATE TEMPORARY TABLE t2 (b BLOB) ENGINE=INNODB;
|
|
|
|
--connection default
|
|
DROP TABLE t2;
|
|
|
|
--connection con1
|
|
DROP TABLE t2;
|
|
|
|
--connection default
|
|
--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/bug28642318.sql
|
|
|
|
--echo # DROP table query fails with unknown table error without patch.
|
|
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug28642318.sql
|
|
|
|
--echo # Clean up
|
|
--connection default
|
|
SET @@session.binlog_format= @save_binlog_format;
|
|
RESET MASTER;
|
|
|
|
--disconnect con1
|
|
--enable_warnings
|