summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Potemkin <epotemkin@mysql.com>2010-08-24 22:20:45 +0400
committerEvgeny Potemkin <epotemkin@mysql.com>2010-08-24 22:20:45 +0400
commit29d01a11072ec8849f80b377895bee4767c4b0ca (patch)
tree7f28c6d7b15d8a77e8b1f04ac2c5ceddb9cc08b7
parentdd1890f48ce27d1cad0d514e388d4704684a17a7 (diff)
parentab4a92f99f1289b9bcc98bd1aa5ab4d0ec2b3232 (diff)
downloadmariadb-git-29d01a11072ec8849f80b377895bee4767c4b0ca.tar.gz
Auto-merged.
-rw-r--r--mysql-test/include/mysqlhotcopy.inc2
-rwxr-xr-xmysql-test/mysql-test-run.pl5
-rw-r--r--mysql-test/r/delayed.result77
-rw-r--r--mysql-test/r/locale.result2
-rw-r--r--mysql-test/r/mysqlbinlog_row.result138
-rw-r--r--mysql-test/r/partition_innodb.result36
-rw-r--r--mysql-test/suite/parts/r/part_ctype_utf32.result14
-rw-r--r--mysql-test/suite/parts/t/part_ctype_utf32.test28
-rw-r--r--mysql-test/t/delayed.test164
-rw-r--r--mysql-test/t/partition_innodb.test57
-rw-r--r--mysys/my_thr_init.c2
-rw-r--r--sql/field.cc2
-rw-r--r--sql/log_event.cc3
-rw-r--r--sql/sql_audit.cc44
-rw-r--r--sql/sql_audit.h1
-rw-r--r--sql/sql_insert.cc105
-rw-r--r--sql/sql_partition.cc21
-rw-r--r--sql/sql_plugin.cc44
-rw-r--r--sql/sql_table.cc75
-rw-r--r--sql/sql_table.h2
20 files changed, 685 insertions, 137 deletions
diff --git a/mysql-test/include/mysqlhotcopy.inc b/mysql-test/include/mysqlhotcopy.inc
index b3fd5e47179..91e0eff1e0f 100644
--- a/mysql-test/include/mysqlhotcopy.inc
+++ b/mysql-test/include/mysqlhotcopy.inc
@@ -5,7 +5,7 @@
--source include/not_windows.inc
--source include/not_embedded.inc
-if ($MYSQLHOTCOPY)
+if (!$MYSQLHOTCOPY)
{
die due to missing mysqlhotcopy tool;
}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 03d0c9eb621..1b965e7079d 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2158,7 +2158,10 @@ sub environment_setup {
mtr_pl_maybe_exists("$bindir/scripts/mysqlhotcopy");
# Since mysqltest interprets the real path as "false" in an if,
# use 1 ("true") to indicate "not exists" so it can be tested for
- $ENV{'MYSQLHOTCOPY'}= $mysqlhotcopy || 1;
+ if ($mysqlhotcopy)
+ {
+ $ENV{'MYSQLHOTCOPY'}= $mysqlhotcopy;
+ }
# ----------------------------------------------------
# perror
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index 2bc77c52bec..4cb97719ff2 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -345,3 +345,80 @@ CREATE TABLE t1 LIKE t2;
ERROR 42S01: Table 't1' already exists
DROP TABLE t2;
DROP TABLE t1;
+#
+# Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED
+#
+# This test is not supposed to work under --ps-protocol since
+# INSERT DELAYED doesn't work under LOCK TABLES with this protocol.
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE TABLE t3 (a INT);
+# Test 1: Using LOCK TABLE
+# Connection con1
+LOCK TABLE t1 WRITE;
+# Connection default
+LOCK TABLE t2 WRITE;
+# Sending:
+INSERT DELAYED INTO t1 VALUES (1);
+# Connection con1
+# Wait until INSERT DELAYED is blocked on table 't1'.
+INSERT DELAYED INTO t2 VALUES (1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+UNLOCK TABLES;
+# Connection default
+# Reaping: INSERT DELAYED INTO t1 VALUES (1)
+UNLOCK TABLES;
+# Test 2: Using ALTER TABLE
+START TRANSACTION;
+SELECT * FROM t1 WHERE a=0;
+a
+# Connection con1
+# Sending:
+ALTER TABLE t1 COMMENT 'test';
+# Connection default
+# Wait until ALTER TABLE is blocked on table 't1'.
+INSERT DELAYED INTO t1 VALUES (3);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+# Connection con1
+# Reaping: ALTER TABLE t1 COMMENT 'test'
+# Test 3: Using RENAME TABLE
+# Connection default
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+# Connection con1
+# Sending:
+RENAME TABLE t1 to t5, t2 to t4;
+# Connection default
+# Wait until RENAME TABLE is blocked on table 't1'.
+INSERT DELAYED INTO t1 VALUES (4);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+# Connection con1
+# Reaping: RENAME TABLE t1 to t5, t2 to t4
+# Connection default
+# Reverting the renames
+RENAME TABLE t5 to t1, t4 to t2;
+# Test 4: Two INSERT DELAYED on the same table
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+# Connection con2
+LOCK TABLE t1 WRITE, t2 WRITE;
+# Connection con1
+# Wait until LOCK TABLE is blocked on table 't2'.
+INSERT DELAYED INTO t1 VALUES (5);
+# Connection default
+# Wait until INSERT DELAYED is blocked on table 't1'.
+INSERT DELAYED INTO t1 VALUES (6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+# Connection con2
+# Reaping: LOCK TABLE t1 WRITE, t2 WRITE
+UNLOCK TABLES;
+# Connection con1
+# Reaping: INSERT DELAYED INTO t1 VALUES (5)
+# Connection con2
+# Connection con1
+# Connection default
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
index b52ed8070f9..aa61d8cd86f 100644
--- a/mysql-test/r/locale.result
+++ b/mysql-test/r/locale.result
@@ -44,7 +44,7 @@ a abmon mon
2006-12-01 Δεκ Δεκέμβριος
SELECT format(123456.789, 3, 'el_GR');
format(123456.789, 3, 'el_GR')
-123456.789
+123456,789
DROP TABLE t1;
#
# Bug#46633 Obsolete Serbian locale name
diff --git a/mysql-test/r/mysqlbinlog_row.result b/mysql-test/r/mysqlbinlog_row.result
index 85416138c6d..7ae1ea36899 100644
--- a/mysql-test/r/mysqlbinlog_row.result
+++ b/mysql-test/r/mysqlbinlog_row.result
@@ -385,7 +385,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -567,7 +567,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -595,7 +595,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -673,7 +673,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -759,7 +759,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -806,7 +806,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -850,7 +850,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -894,7 +894,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -960,7 +960,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1004,7 +1004,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1070,7 +1070,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1114,7 +1114,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1180,7 +1180,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1224,7 +1224,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1290,7 +1290,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1334,7 +1334,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1378,7 +1378,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1439,7 +1439,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1483,7 +1483,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1527,7 +1527,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1572,7 +1572,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1616,7 +1616,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1660,7 +1660,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1704,7 +1704,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1748,7 +1748,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1792,7 +1792,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1836,7 +1836,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1880,7 +1880,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1924,7 +1924,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -1968,7 +1968,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2032,7 +2032,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2076,7 +2076,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2120,7 +2120,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2164,7 +2164,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2230,7 +2230,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2274,7 +2274,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2318,7 +2318,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2362,7 +2362,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2406,7 +2406,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2450,7 +2450,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2494,7 +2494,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2558,7 +2558,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2622,7 +2622,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2666,7 +2666,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2710,7 +2710,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2754,7 +2754,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2798,7 +2798,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2876,7 +2876,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2920,7 +2920,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -2998,7 +2998,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3076,7 +3076,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3120,7 +3120,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3198,7 +3198,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3276,7 +3276,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3320,7 +3320,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3364,7 +3364,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3408,7 +3408,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3452,7 +3452,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3496,7 +3496,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3540,7 +3540,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3584,7 +3584,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3628,7 +3628,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3672,7 +3672,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3716,7 +3716,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3760,7 +3760,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3804,7 +3804,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3848,7 +3848,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -3994,7 +3994,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1
+DROP TABLE `t1` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
@@ -4127,7 +4127,7 @@ COMMIT
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
-DROP TABLE t1,t2
+DROP TABLE `t1`,`t2` /* generated by server */
/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Rotate to master-bin.000002 pos: 4
diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result
index 107ad719e2b..93cb1617d2f 100644
--- a/mysql-test/r/partition_innodb.result
+++ b/mysql-test/r/partition_innodb.result
@@ -1,5 +1,41 @@
drop table if exists t1, t2;
#
+# Bug#54747: Deadlock between REORGANIZE PARTITION and
+# SELECT is not detected
+#
+SET @old_innodb_thread_concurrency:= @@innodb_thread_concurrency;
+SET GLOBAL innodb_thread_concurrency = 1;
+CREATE TABLE t1
+(user_num BIGINT,
+hours SMALLINT,
+KEY user_num (user_num))
+ENGINE = InnoDB
+PARTITION BY RANGE COLUMNS (hours)
+(PARTITION hour_003 VALUES LESS THAN (3),
+PARTITION hour_004 VALUES LESS THAN (4),
+PARTITION hour_005 VALUES LESS THAN (5),
+PARTITION hour_last VALUES LESS THAN (MAXVALUE));
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+BEGIN;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+# con1
+# SEND a ALTER PARTITION which waits on the ongoing transaction.
+ALTER TABLE t1
+REORGANIZE PARTITION hour_003, hour_004 INTO
+(PARTITION oldest VALUES LESS THAN (4));
+# Connection default wait until the ALTER is in 'waiting for table...'
+# state and then continue the transaction by trying a SELECT
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+COMMIT;
+# con1, reaping ALTER.
+# Disconnecting con1 and switching to default. Cleaning up.
+SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
+DROP TABLE t1;
+#
# Bug#50418: DROP PARTITION does not interact with transactions
#
CREATE TABLE t1 (
diff --git a/mysql-test/suite/parts/r/part_ctype_utf32.result b/mysql-test/suite/parts/r/part_ctype_utf32.result
new file mode 100644
index 00000000000..5d52a8eace4
--- /dev/null
+++ b/mysql-test/suite/parts/r/part_ctype_utf32.result
@@ -0,0 +1,14 @@
+#
+# Bug#52121 partition by key on utf32 enum field cause debug assertion: (length % 4) == 0
+#
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE t1 (
+a enum('a') CHARACTER SET utf32 COLLATE utf32_spanish2_ci
+) ENGINE=MYISAM PARTITION BY KEY(a) PARTITIONS 2;
+INSERT INTO t1 VALUES ('a');
+SELECT * FROM t1;
+a
+a
+DROP TABLE t1;
diff --git a/mysql-test/suite/parts/t/part_ctype_utf32.test b/mysql-test/suite/parts/t/part_ctype_utf32.test
new file mode 100644
index 00000000000..12aa1fb3751
--- /dev/null
+++ b/mysql-test/suite/parts/t/part_ctype_utf32.test
@@ -0,0 +1,28 @@
+################################################################################
+# t/partition_ctype_utf32.test #
+# #
+# Purpose: #
+# Tests for partitions + UTF32 #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Alexander Barkov #
+# Original Date: 2010-08-05 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--source include/have_partition.inc
+--source include/have_utf32.inc
+
+--echo #
+--echo # Bug#52121 partition by key on utf32 enum field cause debug assertion: (length % 4) == 0
+--echo #
+
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+ a enum('a') CHARACTER SET utf32 COLLATE utf32_spanish2_ci
+) ENGINE=MYISAM PARTITION BY KEY(a) PARTITIONS 2;
+INSERT INTO t1 VALUES ('a');
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 2bf0d5d2633..5f56cdf54e1 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -388,3 +388,167 @@ CREATE TABLE t1 LIKE t2;
DROP TABLE t2;
DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED
+--echo #
+
+--echo # This test is not supposed to work under --ps-protocol since
+--echo # INSERT DELAYED doesn't work under LOCK TABLES with this protocol.
+--disable_ps_protocol
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE TABLE t3 (a INT);
+
+--echo # Test 1: Using LOCK TABLE
+
+--echo # Connection con1
+connect (con1, localhost, root);
+LOCK TABLE t1 WRITE;
+
+--echo # Connection default
+connection default;
+LOCK TABLE t2 WRITE;
+--echo # Sending:
+--send INSERT DELAYED INTO t1 VALUES (1)
+
+--echo # Connection con1
+connection con1;
+--echo # Wait until INSERT DELAYED is blocked on table 't1'.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock"
+ AND info = "INSERT DELAYED INTO t1 VALUES (1)";
+--source include/wait_condition.inc
+--error ER_LOCK_DEADLOCK
+INSERT DELAYED INTO t2 VALUES (1);
+UNLOCK TABLES;
+
+--echo # Connection default
+connection default;
+--echo # Reaping: INSERT DELAYED INTO t1 VALUES (1)
+--reap
+UNLOCK TABLES;
+
+--echo # Test 2: Using ALTER TABLE
+
+START TRANSACTION;
+SELECT * FROM t1 WHERE a=0;
+
+--echo # Connection con1
+connection con1;
+--echo # Sending:
+--send ALTER TABLE t1 COMMENT 'test'
+
+--echo # Connection default
+connection default;
+--echo # Wait until ALTER TABLE is blocked on table 't1'.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock"
+ AND info = "ALTER TABLE t1 COMMENT 'test'";
+--source include/wait_condition.inc
+--error ER_LOCK_DEADLOCK
+INSERT DELAYED INTO t1 VALUES (3);
+COMMIT;
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: ALTER TABLE t1 COMMENT 'test'
+--reap
+
+--echo # Test 3: Using RENAME TABLE
+
+--echo # Connection default
+connection default;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+
+--echo # Connection con1
+connection con1;
+--echo # Sending:
+--send RENAME TABLE t1 to t5, t2 to t4
+
+--echo # Connection default
+connection default;
+--echo # Wait until RENAME TABLE is blocked on table 't1'.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock"
+ AND info = "RENAME TABLE t1 to t5, t2 to t4";
+--source include/wait_condition.inc
+--error ER_LOCK_DEADLOCK
+INSERT DELAYED INTO t1 VALUES (4);
+COMMIT;
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: RENAME TABLE t1 to t5, t2 to t4
+--reap
+
+--echo # Connection default
+connection default;
+--echo # Reverting the renames
+RENAME TABLE t5 to t1, t4 to t2;
+
+--echo # Test 4: Two INSERT DELAYED on the same table
+
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+
+--echo # Connection con2
+connect (con2, localhost, root);
+--send LOCK TABLE t1 WRITE, t2 WRITE
+
+--echo # Connection con1
+connection con1;
+--echo # Wait until LOCK TABLE is blocked on table 't2'.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock"
+ AND info = "LOCK TABLE t1 WRITE, t2 WRITE";
+--source include/wait_condition.inc
+--send INSERT DELAYED INTO t1 VALUES (5)
+
+--echo # Connection default
+connection default;
+--echo # Wait until INSERT DELAYED is blocked on table 't1'.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock"
+ AND info = "INSERT DELAYED INTO t1 VALUES (5)";
+--source include/wait_condition.inc
+--error ER_LOCK_DEADLOCK
+INSERT DELAYED INTO t1 VALUES (6);
+COMMIT;
+
+--echo # Connection con2
+connection con2;
+--echo # Reaping: LOCK TABLE t1 WRITE, t2 WRITE
+--reap
+UNLOCK TABLES;
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: INSERT DELAYED INTO t1 VALUES (5)
+--reap
+
+--echo # Connection con2
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
+--echo # Connection con1
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+--echo # Connection default
+connection default;
+DROP TABLE t1, t2, t3;
+--enable_ps_protocol
diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test
index f6adf014468..3e9ac2ce2b5 100644
--- a/mysql-test/t/partition_innodb.test
+++ b/mysql-test/t/partition_innodb.test
@@ -9,6 +9,63 @@ drop table if exists t1, t2;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
--echo #
+--echo # Bug#54747: Deadlock between REORGANIZE PARTITION and
+--echo # SELECT is not detected
+--echo #
+
+SET @old_innodb_thread_concurrency:= @@innodb_thread_concurrency;
+SET GLOBAL innodb_thread_concurrency = 1;
+
+CREATE TABLE t1
+(user_num BIGINT,
+ hours SMALLINT,
+ KEY user_num (user_num))
+ENGINE = InnoDB
+PARTITION BY RANGE COLUMNS (hours)
+(PARTITION hour_003 VALUES LESS THAN (3),
+ PARTITION hour_004 VALUES LESS THAN (4),
+ PARTITION hour_005 VALUES LESS THAN (5),
+ PARTITION hour_last VALUES LESS THAN (MAXVALUE));
+
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+
+BEGIN;
+SELECT COUNT(*) FROM t1;
+
+--echo # con1
+--connect (con1,localhost,root,,)
+--echo # SEND a ALTER PARTITION which waits on the ongoing transaction.
+--send
+ALTER TABLE t1
+REORGANIZE PARTITION hour_003, hour_004 INTO
+(PARTITION oldest VALUES LESS THAN (4));
+
+--echo # Connection default wait until the ALTER is in 'waiting for table...'
+--echo # state and then continue the transaction by trying a SELECT
+--connection default
+let $wait_condition =
+SELECT COUNT(*) = 1
+FROM information_schema.processlist
+WHERE INFO like 'ALTER TABLE t1%REORGANIZE PARTITION hour_003, hour_004%'
+AND STATE = 'Waiting for table metadata lock';
+--source include/wait_condition.inc
+SELECT COUNT(*) FROM t1;
+COMMIT;
+
+--echo # con1, reaping ALTER.
+--connection con1
+--reap
+
+--echo # Disconnecting con1 and switching to default. Cleaning up.
+--disconnect con1
+
+--connection default
+
+SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
+DROP TABLE t1;
+
+
+--echo #
--echo # Bug#50418: DROP PARTITION does not interact with transactions
--echo #
CREATE TABLE t1 (
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 236b694726f..045b56b11c2 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -302,6 +302,8 @@ void my_thread_global_end(void)
#ifndef HAVE_GETHOSTBYNAME_R
mysql_mutex_destroy(&LOCK_gethostbyname_r);
#endif
+
+ my_thread_basic_global_init_done= 0;
}
static my_thread_id thread_id= 0;
diff --git a/sql/field.cc b/sql/field.cc
index 3c93ffadac5..fc55426b177 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1329,7 +1329,7 @@ void Field::hash(ulong *nr, ulong *nr2)
else
{
uint len= pack_length();
- CHARSET_INFO *cs= charset();
+ CHARSET_INFO *cs= sort_charset();
cs->coll->hash_sort(cs, ptr, len, nr, nr2);
}
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c1f7836e08a..16290c58685 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -674,7 +674,8 @@ const char* Log_event::get_type_str()
#ifndef MYSQL_CLIENT
Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
- :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), thd(thd_arg)
+ :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg),
+ cache_type(Log_event::EVENT_INVALID_CACHE), thd(thd_arg)
{
server_id= thd->server_id;
when= thd->start_time;
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 7d269d455a9..b7d363dc09a 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -138,6 +138,30 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
/**
+ @brief Acquire audit plugins
+
+ @param[in] thd MySQL thread handle
+ @param[in] event_class Audit event class
+
+ @details Ensure that audit plugins interested in given event
+ class are locked by current thread.
+*/
+void mysql_audit_acquire_plugins(THD *thd, uint event_class)
+{
+ unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
+ DBUG_ENTER("mysql_audit_acquire_plugins");
+ set_audit_mask(event_class_mask, event_class);
+ if (thd && !check_audit_mask(mysql_global_audit_mask, event_class_mask) &&
+ check_audit_mask(thd->audit_class_mask, event_class_mask))
+ {
+ plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
+ add_audit_mask(thd->audit_class_mask, event_class_mask);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
Notify the audit system of an event
@param[in] thd
@@ -151,21 +175,8 @@ void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...)
{
va_list ap;
audit_handler_t *handlers= audit_handlers + event_class;
- unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
-
DBUG_ASSERT(event_class < audit_handlers_count);
-
- set_audit_mask(event_class_mask, event_class);
- /*
- Check to see if we have acquired the audit plugins for the
- required audit event classes.
- */
- if (thd && check_audit_mask(thd->audit_class_mask, event_class_mask))
- {
- plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
- add_audit_mask(thd->audit_class_mask, event_class_mask);
- }
-
+ mysql_audit_acquire_plugins(thd, event_class);
va_start(ap, event_subtype);
(*handlers)(thd, event_subtype, ap);
va_end(ap);
@@ -448,6 +459,11 @@ static void event_class_dispatch(THD *thd, const struct mysql_event *event)
#else /* EMBEDDED_LIBRARY */
+void mysql_audit_acquire_plugins(THD *thd, uint event_class)
+{
+}
+
+
void mysql_audit_initialize()
{
}
diff --git a/sql/sql_audit.h b/sql/sql_audit.h
index 5b6962b9ecb..953e41f1f06 100644
--- a/sql/sql_audit.h
+++ b/sql/sql_audit.h
@@ -29,6 +29,7 @@ extern void mysql_audit_finalize();
extern void mysql_audit_init_thd(THD *thd);
extern void mysql_audit_free_thd(THD *thd);
+extern void mysql_audit_acquire_plugins(THD *thd, uint event_class);
extern void mysql_audit_notify(THD *thd, uint event_class,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 6c23b47997a..5f6ab43e2ea 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -548,10 +548,25 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
DBUG_RETURN(TRUE);
}
- if (delayed_get_table(thd, table_list))
+ /*
+ In order for the deadlock detector to be able to find any deadlocks
+ caused by the handler thread locking this table, we take the metadata
+ lock inside the connection thread. If this goes ok, the ticket is cloned
+ and added to the list of granted locks held by the handler thread.
+ */
+ MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint();
+ if (thd->mdl_context.acquire_lock(&table_list->mdl_request,
+ thd->variables.lock_wait_timeout))
+ /*
+ If a lock can't be acquired, it makes no sense to try normal insert.
+ Therefore we just abort the statement.
+ */
DBUG_RETURN(TRUE);
- if (table_list->table)
+ bool error= FALSE;
+ if (delayed_get_table(thd, table_list))
+ error= TRUE;
+ else if (table_list->table)
{
/*
Open tables used for sub-selects or in stored functions, will also
@@ -560,16 +575,36 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
if (open_and_lock_tables(thd, table_list->next_global, TRUE, 0))
{
end_delayed_insert(thd);
- DBUG_RETURN(TRUE);
+ error= TRUE;
+ }
+ else
+ {
+ /*
+ First table was not processed by open_and_lock_tables(),
+ we need to set updatability flag "by hand".
+ */
+ if (!table_list->derived && !table_list->view)
+ table_list->updatable= 1; // usual table
}
- /*
- First table was not processed by open_and_lock_tables(),
- we need to set updatability flag "by hand".
- */
- if (!table_list->derived && !table_list->view)
- table_list->updatable= 1; // usual table
- DBUG_RETURN(FALSE);
}
+
+ /*
+ If a lock was acquired above, we should release it after
+ handle_delayed_insert() has cloned the ticket. Note that acquire_lock() can
+ succeed because the connection already has the lock. In this case the ticket
+ will be before the mdl_savepoint and we should not release it here.
+ */
+ if (!thd->mdl_context.has_lock(mdl_savepoint, table_list->mdl_request.ticket))
+ thd->mdl_context.release_lock(table_list->mdl_request.ticket);
+
+ /*
+ Reset the ticket in case we end up having to use normal insert and
+ therefore will reopen the table and reacquire the metadata lock.
+ */
+ table_list->mdl_request.ticket= NULL;
+
+ if (error || table_list->table)
+ DBUG_RETURN(error);
#endif
/*
* This is embedded library and we don't have auxiliary
@@ -1801,14 +1836,25 @@ public:
mysql_cond_t cond, cond_client;
volatile uint tables_in_use,stacked_inserts;
volatile bool status;
+ /*
+ When the handler thread starts, it clones a metadata lock ticket
+ for the table to be inserted. This is done to allow the deadlock
+ detector to detect deadlocks resulting from this lock.
+ Before this is done, the connection thread cannot safely exit
+ without causing problems for clone_ticket().
+ Once handler_thread_initialized has been set, it is safe for the
+ connection thread to exit.
+ Access to handler_thread_initialized is protected by di->mutex.
+ */
+ bool handler_thread_initialized;
COPY_INFO info;
I_List<delayed_row> rows;
ulong group_count;
TABLE_LIST table_list; // Argument
Delayed_insert()
- :locks_in_memory(0),
- table(0),tables_in_use(0),stacked_inserts(0), status(0), group_count(0)
+ :locks_in_memory(0), table(0),tables_in_use(0),stacked_inserts(0),
+ status(0), handler_thread_initialized(FALSE), group_count(0)
{
DBUG_ENTER("Delayed_insert constructor");
thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user;
@@ -2025,6 +2071,10 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
/* Replace volatile strings with local copies */
di->table_list.alias= di->table_list.table_name= di->thd.query();
di->table_list.db= di->thd.db;
+ /* We need the ticket so that it can be cloned in handle_delayed_insert */
+ init_mdl_requests(&di->table_list);
+ di->table_list.mdl_request.ticket= table_list->mdl_request.ticket;
+
di->lock();
mysql_mutex_lock(&di->mutex);
if ((error= mysql_thread_create(key_thread_delayed_insert,
@@ -2041,9 +2091,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
goto end_create;
}
- /* Wait until table is open */
+ /*
+ Wait until table is open unless the handler thread or the connection
+ thread has been killed. Note that we in all cases must wait until the
+ handler thread has been properly initialized before exiting. Otherwise
+ we risk doing clone_ticket() on a ticket that is no longer valid.
+ */
thd_proc_info(thd, "waiting for handler open");
- while (!di->thd.killed && !di->table && !thd->killed)
+ while (!di->handler_thread_initialized ||
+ (!di->thd.killed && !di->table && !thd->killed))
{
mysql_cond_wait(&di->cond_client, &di->mutex);
}
@@ -2471,6 +2527,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Can't use my_error since store_globals has not yet been called */
thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES), NULL);
+ di->handler_thread_initialized= TRUE;
}
else
{
@@ -2481,6 +2538,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Can't use my_error since store_globals has perhaps failed */
thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES), NULL);
+ di->handler_thread_initialized= TRUE;
thd->fatal_error();
goto err;
}
@@ -2493,7 +2551,24 @@ pthread_handler_t handle_delayed_insert(void *arg)
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED);
thd->set_current_stmt_binlog_format_row_if_mixed();
- init_mdl_requests(&di->table_list);
+ /*
+ Clone the ticket representing the lock on the target table for
+ the insert and add it to the list of granted metadata locks held by
+ the handler thread. This is safe since the handler thread is
+ not holding nor waiting on any metadata locks.
+ */
+ if (thd->mdl_context.clone_ticket(&di->table_list.mdl_request))
+ {
+ di->handler_thread_initialized= TRUE;
+ goto err;
+ }
+
+ /*
+ Now that the ticket has been cloned, it is safe for the connection
+ thread to exit.
+ */
+ di->handler_thread_initialized= TRUE;
+ di->table_list.mdl_request.ticket= NULL;
if (di->open_and_lock_table())
goto err;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 5bbe946179e..b72816f8ce3 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -63,6 +63,7 @@
#include "sql_table.h" // build_table_filename,
// build_table_shadow_filename,
// table_to_filename
+ // mysql_*_alter_copy_data
#include "opt_range.h" // store_key_image_to_rec
#include "sql_analyse.h" // append_escaped
@@ -4377,7 +4378,6 @@ static int fast_end_partition(THD *thd, ulonglong copied,
ALTER_PARTITION_PARAM_TYPE *lpt,
bool written_bin_log)
{
- int error;
char tmp_name[80];
DBUG_ENTER("fast_end_partition");
@@ -4386,13 +4386,6 @@ static int fast_end_partition(THD *thd, ulonglong copied,
if (!is_empty)
query_cache_invalidate3(thd, table_list, 0);
- error= trans_commit_stmt(thd);
- if (trans_commit_implicit(thd))
- error= 1;
-
- if (error)
- DBUG_RETURN(TRUE); /* The error has been reported */
-
if ((!is_empty) && (!written_bin_log) &&
(!thd->lex->no_write_to_binlog) &&
write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
@@ -5535,17 +5528,25 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
char path[FN_REFLEN+1];
int error;
handler *file= lpt->table->file;
+ THD *thd= lpt->thd;
DBUG_ENTER("mysql_change_partitions");
build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
+
+ if(mysql_trans_prepare_alter_copy_data(thd))
+ DBUG_RETURN(TRUE);
+
if ((error= file->ha_change_partitions(lpt->create_info, path, &lpt->copied,
&lpt->deleted, lpt->pack_frm_data,
lpt->pack_frm_len)))
{
file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
- DBUG_RETURN(TRUE);
}
- DBUG_RETURN(FALSE);
+
+ if (mysql_trans_commit_alter_copy_data(thd))
+ DBUG_RETURN(TRUE); /* The error has been reported */
+
+ DBUG_RETURN(test(error));
}
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 0020741b78f..956be657af2 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -29,7 +29,7 @@
#include "records.h" // init_read_record, end_read_record
#include <my_pthread.h>
#include <my_getopt.h>
-#include <mysql/plugin_audit.h>
+#include "sql_audit.h"
#include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
@@ -1709,6 +1709,27 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
MYSQL_LOCK_IGNORE_TIMEOUT)))
DBUG_RETURN(TRUE);
+ /*
+ Pre-acquire audit plugins for events that may potentially occur
+ during [UN]INSTALL PLUGIN.
+
+ When audit event is triggered, audit subsystem acquires interested
+ plugins by walking through plugin list. Evidently plugin list
+ iterator protects plugin list by acquiring LOCK_plugin, see
+ plugin_foreach_with_mask().
+
+ On the other hand [UN]INSTALL PLUGIN is acquiring LOCK_plugin
+ rather for a long time.
+
+ When audit event is triggered during [UN]INSTALL PLUGIN, plugin
+ list iterator acquires the same lock (within the same thread)
+ second time.
+
+ This hack should be removed when LOCK_plugin is fixed so it
+ protects only what it supposed to protect.
+ */
+ mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+
mysql_mutex_lock(&LOCK_plugin);
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
@@ -1789,6 +1810,27 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
DBUG_RETURN(TRUE);
+ /*
+ Pre-acquire audit plugins for events that may potentially occur
+ during [UN]INSTALL PLUGIN.
+
+ When audit event is triggered, audit subsystem acquires interested
+ plugins by walking through plugin list. Evidently plugin list
+ iterator protects plugin list by acquiring LOCK_plugin, see
+ plugin_foreach_with_mask().
+
+ On the other hand [UN]INSTALL PLUGIN is acquiring LOCK_plugin
+ rather for a long time.
+
+ When audit event is triggered during [UN]INSTALL PLUGIN, plugin
+ list iterator acquires the same lock (within the same thread)
+ second time.
+
+ This hack should be removed when LOCK_plugin is fixed so it
+ protects only what it supposed to protect.
+ */
+ mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+
mysql_mutex_lock(&LOCK_plugin);
if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bd5f381b8b8..3f0a0326c84 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4268,6 +4268,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
Alter_info *alter_info)
{
bool result;
+ bool is_trans= FALSE;
DBUG_ENTER("mysql_create_table");
/*
@@ -4282,7 +4283,6 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
/* Got lock. */
DEBUG_SYNC(thd, "locked_table_name");
- bool is_trans;
result= mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name, create_info,
alter_info, FALSE, 0, &is_trans);
@@ -4454,6 +4454,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
HA_CREATE_INFO local_create_info;
Alter_info local_alter_info;
bool res= TRUE;
+ bool is_trans= FALSE;
uint not_used;
DBUG_ENTER("mysql_create_like_table");
@@ -4503,7 +4504,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
/* Reset auto-increment counter for the new table. */
local_create_info.auto_increment_value= 0;
- bool is_trans;
if ((res= mysql_create_table_no_lock(thd, table->db, table->table_name,
&local_create_info, &local_alter_info,
FALSE, 0, &is_trans)))
@@ -6740,6 +6740,54 @@ err_with_mdl:
}
/* mysql_alter_table */
+
+
+/**
+ Prepare the transaction for the alter table's copy phase.
+*/
+
+bool mysql_trans_prepare_alter_copy_data(THD *thd)
+{
+ DBUG_ENTER("mysql_prepare_alter_copy_data");
+ /*
+ Turn off recovery logging since rollback of an alter table is to
+ delete the new table so there is no need to log the changes to it.
+
+ This needs to be done before external_lock.
+ */
+ if (ha_enable_transaction(thd, FALSE))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Commit the copy phase of the alter table.
+*/
+
+bool mysql_trans_commit_alter_copy_data(THD *thd)
+{
+ bool error= FALSE;
+ DBUG_ENTER("mysql_commit_alter_copy_data");
+
+ if (ha_enable_transaction(thd, TRUE))
+ DBUG_RETURN(TRUE);
+
+ /*
+ Ensure that the new table is saved properly to disk before installing
+ the new .frm.
+ And that InnoDB's internal latches are released, to avoid deadlock
+ when waiting on other instances of the table before rename (Bug#54747).
+ */
+ if (trans_commit_stmt(thd))
+ error= TRUE;
+ if (trans_commit_implicit(thd))
+ error= TRUE;
+
+ DBUG_RETURN(error);
+}
+
+
static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<Create_field> &create,
@@ -6766,14 +6814,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
ulonglong prev_insert_id;
DBUG_ENTER("copy_data_between_tables");
- /*
- Turn off recovery logging since rollback of an alter table is to
- delete the new table so there is no need to log the changes to it.
-
- This needs to be done before external_lock
- */
- error= ha_enable_transaction(thd, FALSE);
- if (error)
+ if (mysql_trans_prepare_alter_copy_data(thd))
DBUG_RETURN(-1);
if (!(copy= new Copy_field[to->s->fields]))
@@ -6932,20 +6973,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
- if (ha_enable_transaction(thd, TRUE))
- {
+ if (mysql_trans_commit_alter_copy_data(thd))
error= 1;
- goto err;
- }
-
- /*
- Ensure that the new table is saved properly to disk so that we
- can do a rename
- */
- if (trans_commit_stmt(thd))
- error=1;
- if (trans_commit_implicit(thd))
- error=1;
err:
thd->variables.sql_mode= save_sql_mode;
diff --git a/sql/sql_table.h b/sql/sql_table.h
index ae5beefea37..eb0b1aa94dd 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -143,6 +143,8 @@ bool mysql_create_table_no_lock(THD *thd, const char *db,
bool mysql_prepare_alter_table(THD *thd, TABLE *table,
HA_CREATE_INFO *create_info,
Alter_info *alter_info);
+bool mysql_trans_prepare_alter_copy_data(THD *thd);
+bool mysql_trans_commit_alter_copy_data(THD *thd);
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,