# At a local mysql-6.0 repository of davi
2842 Davi Arnaut 2008-09-29 [merge]
Merge from 5.1-5.1.29-rc branch.
added:
mysql-test/suite/binlog/r/binlog_stm_row.result
mysql-test/suite/binlog/t/binlog_stm_row.test
modified:
include/thr_lock.h
mysql-test/r/log_tables.result
mysql-test/t/log_tables.test
sql/lock.cc
sql/mysql_priv.h
sql/mysqld.cc
sql/sql_base.cc
sql/sql_parse.cc
sql/sql_update.cc
sql/sql_yacc.yy
=== modified file 'include/thr_lock.h'
--- a/include/thr_lock.h 2008-06-28 11:00:59 +0000
+++ b/include/thr_lock.h 2008-09-29 18:20:59 +0000
@@ -29,6 +29,14 @@ extern ulong locks_immediate,locks_waite
enum thr_lock_type { TL_IGNORE=-1,
TL_UNLOCK, /* UNLOCK ANY LOCK */
+ /*
+ Parser only! At open_tables() becomes TL_READ or
+ TL_READ_NO_INSERT depending on the binary log format
+ (SBR/RBR) and on the table category (log table).
+ Used for tables that are read by statements which
+ modify tables.
+ */
+ TL_READ_DEFAULT,
TL_READ, /* Read lock */
TL_READ_WITH_SHARED_LOCKS,
/* High prior. than TL_WRITE. Allow concurrent insert */
=== modified file 'mysql-test/r/log_tables.result'
--- a/mysql-test/r/log_tables.result 2008-07-07 17:54:50 +0000
+++ b/mysql-test/r/log_tables.result 2008-09-29 18:20:59 +0000
@@ -829,6 +829,35 @@ Execute select '000 001 002 003 004 005
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;
=== added file 'mysql-test/suite/binlog/r/binlog_stm_row.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_row.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_row.result 2008-09-29 13:53:40 +0000
@@ -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;
=== added file 'mysql-test/suite/binlog/t/binlog_stm_row.test'
--- a/mysql-test/suite/binlog/t/binlog_stm_row.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_stm_row.test 2008-09-29 13:53:40 +0000
@@ -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;
=== modified file 'mysql-test/t/log_tables.test'
--- a/mysql-test/t/log_tables.test 2008-07-07 17:54:50 +0000
+++ b/mysql-test/t/log_tables.test 2008-09-29 18:20:59 +0000
@@ -944,6 +944,52 @@ 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
#
SET @old_slow_log_state = @@global.slow_query_log;
=== modified file 'sql/lock.cc'
--- a/sql/lock.cc 2008-07-09 07:12:43 +0000
+++ b/sql/lock.cc 2008-09-29 18:20:59 +0000
@@ -867,7 +867,7 @@ static MYSQL_LOCK *get_lock_data(THD *th
if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
continue;
lock_type= table->reginfo.lock_type;
- DBUG_ASSERT (lock_type != TL_WRITE_DEFAULT);
+ DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
if (lock_type >= TL_WRITE_ALLOW_WRITE)
{
*write_lock_used=table;
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-09-04 13:46:04 +0000
+++ b/sql/mysql_priv.h 2008-09-29 18:20:59 +0000
@@ -1348,6 +1348,7 @@ bool tdc_open_view(THD *thd, TABLE_LIST
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
TABLE *find_write_locked_table(TABLE *list, const char *db,
const char *table_name);
+thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table);
bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam,
@@ -2029,7 +2030,7 @@ extern bool opt_using_transactions;
extern bool mysqld_embedded;
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
#ifdef MYSQL_SERVER
-extern bool using_update_log, opt_large_files, server_id_supplied;
+extern bool opt_large_files, server_id_supplied;
extern bool opt_update_log, opt_bin_log, opt_error_log;
extern my_bool opt_log, opt_slow_log;
extern ulong log_output_options;
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-09-09 19:02:38 +0000
+++ b/sql/mysqld.cc 2008-09-29 18:20:59 +0000
@@ -438,7 +438,7 @@ my_bool opt_character_set_client_handsha
bool server_id_supplied = 0;
bool opt_endinfo, using_udf_functions;
my_bool locked_in_memory;
-bool opt_using_transactions, using_update_log;
+bool opt_using_transactions;
bool volatile abort_loop;
bool volatile shutdown_in_progress;
/**
@@ -4025,12 +4025,6 @@ server.");
{
unireg_abort(1);
}
-
- /*
- Used to specify which type of lock we need to use for queries of type
- INSERT ... SELECT. This will change when we have row level logging.
- */
- using_update_log=1;
}
/* call ha_init_key_cache() on all key caches to init them */
@@ -7686,7 +7680,7 @@ static void mysql_init_variables(void)
slave_open_temp_tables= 0;
cached_thread_count= 0;
opt_endinfo= using_udf_functions= 0;
- opt_using_transactions= using_update_log= 0;
+ opt_using_transactions= 0;
abort_loop= select_thread_in_use= signal_thread_in_use= 0;
ready_to_exit= shutdown_in_progress= grant_option= 0;
aborted_threads= aborted_connects= 0;
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-09-18 09:06:39 +0000
+++ b/sql/sql_base.cc 2008-09-29 18:20:59 +0000
@@ -3494,6 +3494,38 @@ recover_from_failed_open_table_attempt(T
/*
+ Return a appropriate read lock type given a table object.
+
+ @param thd Thread context
+ @param table TABLE object for table to be locked
+
+ @remark Due to a statement-based replication limitation, statements such as
+ INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need
+ to grab a TL_READ_NO_INSERT lock on the source table in order to
+ prevent the replication of a concurrent statement that modifies the
+ source table. If such a statement gets applied on the slave before
+ the INSERT .. SELECT statement finishes, data on the master could
+ differ from data on the slave and end-up with a discrepancy between
+ the binary log and table state. Furthermore, this does not apply to
+ I_S and log tables as it's always unsafe to replicate such tables
+ under statement-based replication as the table on the slave might
+ contain other data (ie: general_log is enabled on the slave). The
+ statement will be marked as unsafe for SBR in decide_logging_format().
+*/
+
+thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table)
+{
+ bool log_on= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
+ ulong binlog_format= thd->variables.binlog_format;
+ if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) ||
+ (table->s->table_category == TABLE_CATEGORY_PERFORMANCE))
+ return TL_READ;
+ else
+ return TL_READ_NO_INSERT;
+}
+
+
+/*
Open all tables in list
SYNOPSIS
@@ -3785,6 +3817,9 @@ int open_tables(THD *thd, TABLE_LIST **s
{
if (tables->lock_type == TL_WRITE_DEFAULT)
tables->table->reginfo.lock_type= thd->update_lock_default;
+ else if (tables->lock_type == TL_READ_DEFAULT)
+ tables->table->reginfo.lock_type=
+ read_lock_type_for_table(thd, tables->table);
else if (tables->table->s->tmp_table == NO_TMP_TABLE)
tables->table->reginfo.lock_type= tables->lock_type;
}
@@ -4234,7 +4269,11 @@ int decide_logging_format(THD *thd, TABL
void* prev_ht= NULL;
for (TABLE_LIST *table= tables; table; table= table->next_global)
{
- if (!table->placeholder() && table->lock_type >=
TL_WRITE_ALLOW_WRITE)
+ if (table->placeholder())
+ continue;
+ if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
+ thd->lex->set_stmt_unsafe();
+ if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
{
ulonglong const flags= table->table->file->ha_table_flags();
DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s",
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-09-10 12:50:02 +0000
+++ b/sql/sql_parse.cc 2008-09-29 18:20:59 +0000
@@ -5841,7 +5841,7 @@ void mysql_init_multi_delete(LEX *lex)
lex->select_lex.select_limit= 0;
lex->unit.select_limit_cnt= HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
- lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
+ lex->lock_option= TL_READ_DEFAULT;
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
}
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2008-08-28 09:59:54 +0000
+++ b/sql/sql_update.cc 2008-09-29 18:20:59 +0000
@@ -1046,7 +1046,7 @@ reopen_tables:
correct order of statements. Otherwise, we use a TL_READ lock to
improve performance.
*/
- tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ;
+ tl->lock_type= read_lock_type_for_table(thd, table);
tl->updating= 0;
/* Update TABLE::lock_type accordingly. */
if (!tl->placeholder() && !using_lock_tables)
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2008-09-18 09:06:39 +0000
+++ b/sql/sql_yacc.yy 2008-09-29 18:20:59 +0000
@@ -4461,7 +4461,7 @@ create_select:
SELECT_SYM
{
LEX *lex=Lex;
- lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
+ lex->lock_option= TL_READ_DEFAULT;
if (lex->sql_command == SQLCOM_INSERT)
lex->sql_command= SQLCOM_INSERT_SELECT;
else if (lex->sql_command == SQLCOM_REPLACE)
@@ -9923,7 +9923,7 @@ insert:
lex->duplicates= DUP_ERROR;
mysql_init_select(lex);
/* for subselects */
- lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
+ lex->lock_option= TL_READ_DEFAULT;
}
insert_lock_option
opt_ignore insert2
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (davi:2842) | Davi Arnaut | 29 Sep |