summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/probes_mysql_nodtrace.h129
-rw-r--r--mysql-test/include/mtr_warnings.sql8
-rw-r--r--mysql-test/lib/v1/mtr_report.pl3
-rw-r--r--mysql-test/r/create.result19
-rw-r--r--mysql-test/r/innodb_mysql_lock.result32
-rw-r--r--mysql-test/r/lock.result2
-rw-r--r--mysql-test/r/merge.result30
-rw-r--r--mysql-test/r/repair.result12
-rw-r--r--mysql-test/r/view.result6
-rw-r--r--mysql-test/t/create.test30
-rw-r--r--mysql-test/t/innodb_mysql_lock.test63
-rw-r--r--mysql-test/t/merge.test39
-rw-r--r--mysql-test/t/repair.test15
-rw-r--r--mysys/thr_lock.c32
-rw-r--r--sql/lock.cc93
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_insert.cc41
-rw-r--r--sql/sql_parse.cc138
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_trigger.cc6
22 files changed, 495 insertions, 230 deletions
diff --git a/include/probes_mysql_nodtrace.h b/include/probes_mysql_nodtrace.h
deleted file mode 100644
index bc3b65a00e5..00000000000
--- a/include/probes_mysql_nodtrace.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Generated by dheadgen(1).
- */
-
-#ifndef _PROBES_MYSQL_D
-#define _PROBES_MYSQL_D
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MYSQL_CONNECTION_START(arg0, arg1, arg2)
-#define MYSQL_CONNECTION_START_ENABLED() (0)
-#define MYSQL_CONNECTION_DONE(arg0, arg1)
-#define MYSQL_CONNECTION_DONE_ENABLED() (0)
-#define MYSQL_COMMAND_START(arg0, arg1, arg2, arg3)
-#define MYSQL_COMMAND_START_ENABLED() (0)
-#define MYSQL_COMMAND_DONE(arg0)
-#define MYSQL_COMMAND_DONE_ENABLED() (0)
-#define MYSQL_QUERY_START(arg0, arg1, arg2, arg3, arg4)
-#define MYSQL_QUERY_START_ENABLED() (0)
-#define MYSQL_QUERY_DONE(arg0)
-#define MYSQL_QUERY_DONE_ENABLED() (0)
-#define MYSQL_QUERY_PARSE_START(arg0)
-#define MYSQL_QUERY_PARSE_START_ENABLED() (0)
-#define MYSQL_QUERY_PARSE_DONE(arg0)
-#define MYSQL_QUERY_PARSE_DONE_ENABLED() (0)
-#define MYSQL_QUERY_CACHE_HIT(arg0, arg1)
-#define MYSQL_QUERY_CACHE_HIT_ENABLED() (0)
-#define MYSQL_QUERY_CACHE_MISS(arg0)
-#define MYSQL_QUERY_CACHE_MISS_ENABLED() (0)
-#define MYSQL_QUERY_EXEC_START(arg0, arg1, arg2, arg3, arg4, arg5)
-#define MYSQL_QUERY_EXEC_START_ENABLED() (0)
-#define MYSQL_QUERY_EXEC_DONE(arg0)
-#define MYSQL_QUERY_EXEC_DONE_ENABLED() (0)
-#define MYSQL_INSERT_ROW_START(arg0, arg1)
-#define MYSQL_INSERT_ROW_START_ENABLED() (0)
-#define MYSQL_INSERT_ROW_DONE(arg0)
-#define MYSQL_INSERT_ROW_DONE_ENABLED() (0)
-#define MYSQL_UPDATE_ROW_START(arg0, arg1)
-#define MYSQL_UPDATE_ROW_START_ENABLED() (0)
-#define MYSQL_UPDATE_ROW_DONE(arg0)
-#define MYSQL_UPDATE_ROW_DONE_ENABLED() (0)
-#define MYSQL_DELETE_ROW_START(arg0, arg1)
-#define MYSQL_DELETE_ROW_START_ENABLED() (0)
-#define MYSQL_DELETE_ROW_DONE(arg0)
-#define MYSQL_DELETE_ROW_DONE_ENABLED() (0)
-#define MYSQL_READ_ROW_START(arg0, arg1, arg2)
-#define MYSQL_READ_ROW_START_ENABLED() (0)
-#define MYSQL_READ_ROW_DONE(arg0)
-#define MYSQL_READ_ROW_DONE_ENABLED() (0)
-#define MYSQL_INDEX_READ_ROW_START(arg0, arg1)
-#define MYSQL_INDEX_READ_ROW_START_ENABLED() (0)
-#define MYSQL_INDEX_READ_ROW_DONE(arg0)
-#define MYSQL_INDEX_READ_ROW_DONE_ENABLED() (0)
-#define MYSQL_HANDLER_RDLOCK_START(arg0, arg1)
-#define MYSQL_HANDLER_RDLOCK_START_ENABLED() (0)
-#define MYSQL_HANDLER_WRLOCK_START(arg0, arg1)
-#define MYSQL_HANDLER_WRLOCK_START_ENABLED() (0)
-#define MYSQL_HANDLER_UNLOCK_START(arg0, arg1)
-#define MYSQL_HANDLER_UNLOCK_START_ENABLED() (0)
-#define MYSQL_HANDLER_RDLOCK_DONE(arg0)
-#define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() (0)
-#define MYSQL_HANDLER_WRLOCK_DONE(arg0)
-#define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() (0)
-#define MYSQL_HANDLER_UNLOCK_DONE(arg0)
-#define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() (0)
-#define MYSQL_FILESORT_START(arg0, arg1)
-#define MYSQL_FILESORT_START_ENABLED() (0)
-#define MYSQL_FILESORT_DONE(arg0, arg1)
-#define MYSQL_FILESORT_DONE_ENABLED() (0)
-#define MYSQL_SELECT_START(arg0)
-#define MYSQL_SELECT_START_ENABLED() (0)
-#define MYSQL_SELECT_DONE(arg0, arg1)
-#define MYSQL_SELECT_DONE_ENABLED() (0)
-#define MYSQL_INSERT_START(arg0)
-#define MYSQL_INSERT_START_ENABLED() (0)
-#define MYSQL_INSERT_DONE(arg0, arg1)
-#define MYSQL_INSERT_DONE_ENABLED() (0)
-#define MYSQL_INSERT_SELECT_START(arg0)
-#define MYSQL_INSERT_SELECT_START_ENABLED() (0)
-#define MYSQL_INSERT_SELECT_DONE(arg0, arg1)
-#define MYSQL_INSERT_SELECT_DONE_ENABLED() (0)
-#define MYSQL_UPDATE_START(arg0)
-#define MYSQL_UPDATE_START_ENABLED() (0)
-#define MYSQL_UPDATE_DONE(arg0, arg1, arg2)
-#define MYSQL_UPDATE_DONE_ENABLED() (0)
-#define MYSQL_MULTI_UPDATE_START(arg0)
-#define MYSQL_MULTI_UPDATE_START_ENABLED() (0)
-#define MYSQL_MULTI_UPDATE_DONE(arg0, arg1, arg2)
-#define MYSQL_MULTI_UPDATE_DONE_ENABLED() (0)
-#define MYSQL_DELETE_START(arg0)
-#define MYSQL_DELETE_START_ENABLED() (0)
-#define MYSQL_DELETE_DONE(arg0, arg1)
-#define MYSQL_DELETE_DONE_ENABLED() (0)
-#define MYSQL_MULTI_DELETE_START(arg0)
-#define MYSQL_MULTI_DELETE_START_ENABLED() (0)
-#define MYSQL_MULTI_DELETE_DONE(arg0, arg1)
-#define MYSQL_MULTI_DELETE_DONE_ENABLED() (0)
-#define MYSQL_NET_READ_START()
-#define MYSQL_NET_READ_START_ENABLED() (0)
-#define MYSQL_NET_READ_DONE(arg0, arg1)
-#define MYSQL_NET_READ_DONE_ENABLED() (0)
-#define MYSQL_NET_WRITE_START(arg0)
-#define MYSQL_NET_WRITE_START_ENABLED() (0)
-#define MYSQL_NET_WRITE_DONE(arg0)
-#define MYSQL_NET_WRITE_DONE_ENABLED() (0)
-#define MYSQL_KEYCACHE_READ_START(arg0, arg1, arg2, arg3)
-#define MYSQL_KEYCACHE_READ_START_ENABLED() (0)
-#define MYSQL_KEYCACHE_READ_BLOCK(arg0)
-#define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() (0)
-#define MYSQL_KEYCACHE_READ_HIT()
-#define MYSQL_KEYCACHE_READ_HIT_ENABLED() (0)
-#define MYSQL_KEYCACHE_READ_MISS()
-#define MYSQL_KEYCACHE_READ_MISS_ENABLED() (0)
-#define MYSQL_KEYCACHE_READ_DONE(arg0, arg1)
-#define MYSQL_KEYCACHE_READ_DONE_ENABLED() (0)
-#define MYSQL_KEYCACHE_WRITE_START(arg0, arg1, arg2, arg3)
-#define MYSQL_KEYCACHE_WRITE_START_ENABLED() (0)
-#define MYSQL_KEYCACHE_WRITE_BLOCK(arg0)
-#define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() (0)
-#define MYSQL_KEYCACHE_WRITE_DONE(arg0, arg1)
-#define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() (0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PROBES_MYSQL_D */
diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql
index e03e83efac2..14f1dd97830 100644
--- a/mysql-test/include/mtr_warnings.sql
+++ b/mysql-test/include/mtr_warnings.sql
@@ -186,6 +186,14 @@ INSERT INTO global_suppressions VALUES
(": The MySQL server is running with the --secure-backup-file-priv option so it cannot execute this statement"),
("Slave: Unknown table 't1' Error_code: 1051"),
+ /*
+ BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB
+ table cause warnings in errlog
+ Note: This is a temporary suppression until Bug#42147 can be
+ fixed properly. See bug page for more information.
+ */
+ ("Found lock of type 6 that is write and read locked"),
+
("THE_LAST_SUPPRESSION")||
diff --git a/mysql-test/lib/v1/mtr_report.pl b/mysql-test/lib/v1/mtr_report.pl
index 3c78c3ca064..36aba983c34 100644
--- a/mysql-test/lib/v1/mtr_report.pl
+++ b/mysql-test/lib/v1/mtr_report.pl
@@ -376,6 +376,9 @@ sub mtr_report_stats ($) {
/Slave: Can't DROP 'c7'.* 1091/ or
/Slave: Key column 'c6'.* 1072/ or
+ # Warnings generated until bug#42147 is properly resolved
+ /Found lock of type 6 that is write and read locked/ or
+
# rpl_idempotency.test produces warnings for the slave.
($testname eq 'rpl.rpl_idempotency' and
(/Slave: Can\'t find record in \'t1\' Error_code: 1032/ or
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index cf424b8b058..66439593c7c 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1961,3 +1961,22 @@ END ;|
ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'
DROP TABLE t1;
DROP TABLE B;
+#
+# Bug #47107 assert in notify_shared_lock on incorrect
+# CREATE TABLE , HANDLER
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(f1 integer);
+# The following CREATE TABLEs before gave an assert.
+HANDLER t1 OPEN AS A;
+CREATE TABLE t1 SELECT 1 AS f2;
+ERROR 42S01: Table 't1' already exists
+HANDLER t1 OPEN AS A;
+CREATE TABLE t1(f1 integer);
+ERROR 42S01: Table 't1' already exists
+CREATE TABLE t2(f1 integer);
+HANDLER t1 OPEN AS A;
+CREATE TABLE t1 LIKE t2;
+ERROR 42S01: Table 't1' already exists
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/mysql-test/r/innodb_mysql_lock.result b/mysql-test/r/innodb_mysql_lock.result
index 147267d5550..374f67358eb 100644
--- a/mysql-test/r/innodb_mysql_lock.result
+++ b/mysql-test/r/innodb_mysql_lock.result
@@ -21,4 +21,36 @@ INSERT INTO t1 VALUES (2);
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
# Cleanup
commit;
+set @@autocommit=1;
commit;
+set @@autocommit=1;
+set @@autocommit=1;
+#
+# Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
+# table cause warnings in errlog
+#
+#
+# Note that this test for now relies on a global suppression of
+# the warning "Found lock of type 6 that is write and read locked"
+# This suppression rule can be removed once Bug#42147 is properly
+# fixed. See bug page for more info.
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT) engine= innodb;
+# Connection 2
+# Get user-level lock
+SELECT get_lock('bug42147_lock', 60);
+get_lock('bug42147_lock', 60)
+1
+# Connection 1
+INSERT INTO t1 SELECT get_lock('bug42147_lock', 60);
+# Connection 2
+LOCK TABLES t1 READ;
+SELECT release_lock('bug42147_lock');
+release_lock('bug42147_lock')
+1
+# Connection 1
+# Connection 2
+UNLOCK TABLES;
+# Connection 1
+DROP TABLE t1;
diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result
index a542d70c5b9..8f680858fdc 100644
--- a/mysql-test/r/lock.result
+++ b/mysql-test/r/lock.result
@@ -41,7 +41,7 @@ lock tables t1 write;
check table t2;
Table Op Msg_type Msg_text
test.t2 check Error Table 't2' was not locked with LOCK TABLES
-test.t2 check error Corrupt
+test.t2 check status Operation failed
insert into t1 select index1,nr from t1;
ERROR HY000: Table 't1' was not locked with LOCK TABLES
unlock tables;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 479645744ec..3a6cd4d3f5a 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -2502,4 +2502,34 @@ c1
DROP TRIGGER t2_au;
DROP FUNCTION f1;
DROP TABLE tm1, t1, t2, t3, t4, t5;
+#
+# Bug47098 assert in MDL_context::destroy on HANDLER
+# <damaged merge table> OPEN
+#
+# Test that merge tables are closed correctly when opened using
+# HANDLER ... OPEN.
+# The general case.
+DROP TABLE IF EXISTS t1, t2, t3;
+# Connection con1.
+CREATE TABLE t1 (c1 int);
+CREATE TABLE t2 (c1 int);
+CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
+START TRANSACTION;
+HANDLER t3 OPEN;
+ERROR HY000: Table storage engine for 't3' doesn't have this option
+DROP TABLE t1, t2, t3;
+# Connection default.
+# Disconnecting con1, all mdl_tickets must have been released.
+# The bug-specific case.
+# Connection con1.
+CREATE TABLE t1 (c1 int);
+CREATE TABLE t2 (c1 int);
+CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
+DROP TABLE t2;
+START TRANSACTION;
+HANDLER t3 OPEN;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, t3;
+# Connection default.
+# Disconnecting con1, all mdl_tickets must have been released.
End of 6.0 tests
diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result
index 5bb3dd76fed..77eb927a21f 100644
--- a/mysql-test/r/repair.result
+++ b/mysql-test/r/repair.result
@@ -157,3 +157,15 @@ REPAIR TABLE tt1 USE_FRM;
Table Op Msg_type Msg_text
tt1 repair error Cannot repair temporary table from .frm file
DROP TABLE tt1;
+#
+# Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT);
+LOCK TABLES t1 READ;
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair Error Table 't1' was locked with a READ lock and can't be updated
+test.t1 repair status Operation failed
+UNLOCK TABLES;
+DROP TABLE t1;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 5f16d88a0dc..7e9739173df 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -1955,15 +1955,15 @@ CHECK TABLE v1, v2, v3, v4, v5, v6;
Table Op Msg_type Msg_text
test.v1 check Error FUNCTION test.f1 does not exist
test.v1 check Error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
-test.v1 check error Corrupt
+test.v1 check status Operation failed
test.v2 check status OK
test.v3 check Error FUNCTION test.f1 does not exist
test.v3 check Error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
-test.v3 check error Corrupt
+test.v3 check status Operation failed
test.v4 check status OK
test.v5 check Error FUNCTION test.f1 does not exist
test.v5 check Error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
-test.v5 check error Corrupt
+test.v5 check status Operation failed
test.v6 check status OK
create function f1 () returns int return (select max(col1) from t1);
DROP TABLE t1;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index c07014bfc19..21778e00ab9 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -1639,3 +1639,33 @@ END ;|
DROP TABLE t1;
DROP TABLE B;
+
+
+--echo #
+--echo # Bug #47107 assert in notify_shared_lock on incorrect
+--echo # CREATE TABLE , HANDLER
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(f1 integer);
+
+--echo # The following CREATE TABLEs before gave an assert.
+
+HANDLER t1 OPEN AS A;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 SELECT 1 AS f2;
+
+HANDLER t1 OPEN AS A;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1(f1 integer);
+
+CREATE TABLE t2(f1 integer);
+HANDLER t1 OPEN AS A;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 LIKE t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb_mysql_lock.test b/mysql-test/t/innodb_mysql_lock.test
index daee94bedb5..c8c38cd1ab1 100644
--- a/mysql-test/t/innodb_mysql_lock.test
+++ b/mysql-test/t/innodb_mysql_lock.test
@@ -1,5 +1,8 @@
-- source include/have_innodb.inc
+# Save the initial number of concurrent sessions.
+--source include/count_sessions.inc
+
--echo #
--echo # Bug #22876 Four-way deadlock
--echo #
@@ -51,8 +54,68 @@ INSERT INTO t1 VALUES (2);
connection con2;
--reap
commit;
+set @@autocommit=1;
connection con1;
commit;
+set @@autocommit=1;
connection con3;
--reap
+set @@autocommit=1;
connection default;
+
+disconnect con1;
+disconnect con3;
+
+--echo #
+--echo # Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
+--echo # table cause warnings in errlog
+--echo #
+
+--echo #
+--echo # Note that this test for now relies on a global suppression of
+--echo # the warning "Found lock of type 6 that is write and read locked"
+--echo # This suppression rule can be removed once Bug#42147 is properly
+--echo # fixed. See bug page for more info.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT) engine= innodb;
+
+--echo # Connection 2
+--echo # Get user-level lock
+connection con2;
+SELECT get_lock('bug42147_lock', 60);
+
+--echo # Connection 1
+connection default;
+--send INSERT INTO t1 SELECT get_lock('bug42147_lock', 60)
+
+--echo # Connection 2
+connection con2;
+let $wait_condition=
+ SELECT COUNT(*) > 0 FROM information_schema.processlist
+ WHERE state = 'User lock'
+ AND info = 'INSERT INTO t1 SELECT get_lock(\'bug42147_lock\', 60)';
+--source include/wait_condition.inc
+LOCK TABLES t1 READ;
+SELECT release_lock('bug42147_lock');
+
+--echo # Connection 1
+connection default;
+--reap
+
+--echo # Connection 2
+connection con2;
+UNLOCK TABLES;
+
+--echo # Connection 1
+connection default;
+disconnect con2;
+DROP TABLE t1;
+
+# Check that all connections opened by test cases in this file are really
+# gone so execution of other tests won't be affected by their presence.
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index f7ce6ba700b..2738f79247f 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -1985,6 +1985,43 @@ DROP TRIGGER t2_au;
DROP FUNCTION f1;
DROP TABLE tm1, t1, t2, t3, t4, t5;
-
+--echo #
+--echo # Bug47098 assert in MDL_context::destroy on HANDLER
+--echo # <damaged merge table> OPEN
+--echo #
+--echo # Test that merge tables are closed correctly when opened using
+--echo # HANDLER ... OPEN.
+--echo # The general case.
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t3;
+--enable_warnings
+--echo # Connection con1.
+connect (con1,localhost,root,,);
+CREATE TABLE t1 (c1 int);
+CREATE TABLE t2 (c1 int);
+CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
+START TRANSACTION;
+--error ER_ILLEGAL_HA
+HANDLER t3 OPEN;
+DROP TABLE t1, t2, t3;
+--echo # Connection default.
+connection default;
+--echo # Disconnecting con1, all mdl_tickets must have been released.
+disconnect con1;
+--echo # The bug-specific case.
+--echo # Connection con1.
+connect (con1,localhost,root,,);
+CREATE TABLE t1 (c1 int);
+CREATE TABLE t2 (c1 int);
+CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
+DROP TABLE t2;
+START TRANSACTION;
+--error ER_WRONG_MRG_TABLE
+HANDLER t3 OPEN;
+DROP TABLE t1, t3;
+--echo # Connection default.
+connection default;
+--echo # Disconnecting con1, all mdl_tickets must have been released.
+disconnect con1;
--echo End of 6.0 tests
diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test
index eb2ca7992a6..ec4c9b3cae8 100644
--- a/mysql-test/t/repair.test
+++ b/mysql-test/t/repair.test
@@ -158,3 +158,18 @@ CREATE TEMPORARY TABLE tt1 (c1 INT);
REPAIR TABLE tt1 USE_FRM;
DROP TABLE tt1;
+
+--echo #
+--echo # Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+LOCK TABLES t1 READ;
+REPAIR TABLE t1;
+
+UNLOCK TABLES;
+DROP TABLE t1;
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 6433c04a96f..a3f3e9ee080 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -540,13 +540,31 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
/* Request for READ lock */
if (lock->write.data)
{
- /* We can allow a read lock even if there is already a write lock
- on the table in one the following cases:
- - This thread alread have a write lock on the table
- - The write lock is TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED
- and the read lock is TL_READ_HIGH_PRIORITY or TL_READ
- - The write lock is TL_WRITE_CONCURRENT_INSERT or TL_WRITE_ALLOW_WRITE
- and the read lock is not TL_READ_NO_INSERT
+ /*
+ We can allow a read lock even if there is already a
+ write lock on the table if they are owned by the same
+ thread or if they satisfy the following lock
+ compatibility matrix:
+
+ Request
+ /-------
+ H|++++ WRITE_ALLOW_WRITE
+ e|+++- WRITE_ALLOW_READ
+ l|+++- WRITE_CONCURRENT_INSERT
+ d|++++ WRITE_DELAYED
+ ||||
+ |||\= READ_NO_INSERT
+ ||\ = READ_HIGH_PRIORITY
+ |\ = READ_WITH_SHARED_LOCKS
+ \ = READ
+
+ + = Request can be satisified.
+ - = Request cannot be satisified.
+
+ READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle
+ be incompatible. However this will cause starvation of
+ LOCK TABLE READ in InnoDB under high write load.
+ See Bug#42147 for more information.
*/
DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",
diff --git a/sql/lock.cc b/sql/lock.cc
index 648fecf9b69..b64f7b0b44c 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1099,6 +1099,19 @@ static volatile uint waiting_for_read_lock=0;
#define GOT_GLOBAL_READ_LOCK 1
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
+/**
+ Take global read lock, wait if there is protection against lock.
+
+ If the global read lock is already taken by this thread, then nothing is done.
+
+ See also "Handling of global read locks" above.
+
+ @param thd Reference to thread.
+
+ @retval False Success, global read lock set, commits are NOT blocked.
+ @retval True Failure, thread was killed.
+*/
+
bool lock_global_read_lock(THD *thd)
{
DBUG_ENTER("lock_global_read_lock");
@@ -1165,6 +1178,16 @@ bool lock_global_read_lock(THD *thd)
}
+/**
+ Unlock global read lock.
+
+ Commits may or may not be blocked when this function is called.
+
+ See also "Handling of global read locks" above.
+
+ @param thd Reference to thread.
+*/
+
void unlock_global_read_lock(THD *thd)
{
uint tmp;
@@ -1191,6 +1214,25 @@ void unlock_global_read_lock(THD *thd)
DBUG_VOID_RETURN;
}
+/**
+ Wait if the global read lock is set, and optionally seek protection against
+ global read lock.
+
+ See also "Handling of global read locks" above.
+
+ @param thd Reference to thread.
+ @param abort_on_refresh If True, abort waiting if a refresh occurs,
+ do NOT seek protection against GRL.
+ If False, wait until the GRL is released and seek
+ protection against GRL.
+ @param is_not_commit If False, called from a commit operation,
+ wait only if commit blocking is also enabled.
+
+ @retval False Success, protection against global read lock is set
+ (if !abort_on_refresh)
+ @retval True Failure, wait was aborted or thread was killed.
+*/
+
#define must_wait (global_read_lock && \
(is_not_commit || \
global_read_lock_blocks_commit))
@@ -1203,6 +1245,16 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
DBUG_ENTER("wait_if_global_read_lock");
/*
+ If we already have protection against global read lock,
+ just increment the counter.
+ */
+ if (unlikely(thd->global_read_lock_protection > 0))
+ {
+ if (!abort_on_refresh)
+ thd->global_read_lock_protection++;
+ DBUG_RETURN(FALSE);
+ }
+ /*
Assert that we do not own LOCK_open. If we would own it, other
threads could not close their tables. This would make a pretty
deadlock.
@@ -1238,7 +1290,12 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
result=1;
}
if (!abort_on_refresh && !result)
+ {
+ thd->global_read_lock_protection++;
protect_against_global_read_lock++;
+ DBUG_PRINT("sql_lock", ("protect_against_global_read_lock incr: %u",
+ protect_against_global_read_lock));
+ }
/*
The following is only true in case of a global read locks (which is rare)
and if old_message is set
@@ -1251,10 +1308,31 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
}
+/**
+ Release protection against global read lock and restart
+ global read lock waiters.
+
+ Should only be called if we have protection against global read lock.
+
+ See also "Handling of global read locks" above.
+
+ @param thd Reference to thread.
+*/
+
void start_waiting_global_read_lock(THD *thd)
{
bool tmp;
DBUG_ENTER("start_waiting_global_read_lock");
+ /*
+ Ignore request if we do not have protection against global read lock.
+ (Note that this is a violation of the interface contract, hence the assert).
+ */
+ DBUG_ASSERT(thd->global_read_lock_protection > 0);
+ if (unlikely(thd->global_read_lock_protection == 0))
+ DBUG_VOID_RETURN;
+ /* Decrement local read lock protection counter, return if we still have it */
+ if (unlikely(--thd->global_read_lock_protection > 0))
+ DBUG_VOID_RETURN;
if (unlikely(thd->global_read_lock))
DBUG_VOID_RETURN;
(void) pthread_mutex_lock(&LOCK_global_read_lock);
@@ -1268,6 +1346,21 @@ void start_waiting_global_read_lock(THD *thd)
}
+/**
+ Make global read lock also block commits.
+
+ The scenario is:
+ - This thread has the global read lock.
+ - Global read lock blocking of commits is not set.
+
+ See also "Handling of global read locks" above.
+
+ @param thd Reference to thread.
+
+ @retval False Success, global read lock set, commits are blocked.
+ @retval True Failure, thread was killed.
+*/
+
bool make_global_read_lock_block_commit(THD *thd)
{
bool error;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index d83b60810ab..d42a06b3811 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -452,6 +452,7 @@ THD::THD()
examined_row_count(0),
warning_info(&main_warning_info),
stmt_da(&main_da),
+ global_read_lock_protection(0),
global_read_lock(0),
is_fatal_error(0),
transaction_rollback_request(0),
diff --git a/sql/sql_class.h b/sql/sql_class.h
index f4504bfed0d..889d7c5472b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1874,6 +1874,7 @@ public:
ulong rand_saved_seed1, rand_saved_seed2;
pthread_t real_id; /* For debugging */
my_thread_id thread_id;
+ uint global_read_lock_protection;// GRL protection count
uint tmp_table, global_read_lock;
uint server_status,open_options;
enum enum_thread_type system_thread;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index a7fe5a03f10..1966c7d8b39 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -321,6 +321,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
can close a single table only.
*/
close_thread_tables(thd);
+ thd->mdl_context.release_all_locks();
my_error(ER_ILLEGAL_HA, MYF(0), hash_tables->alias);
error= TRUE;
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e0537c75e07..171c5e2cee0 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1974,6 +1974,11 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
}
pthread_mutex_unlock(&di->mutex);
thd_proc_info(thd, "got old table");
+ if (thd->killed)
+ {
+ di->unlock();
+ goto end_create;
+ }
if (di->thd.killed)
{
if (di->thd.is_error())
@@ -1981,20 +1986,19 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
/*
Copy the error message. Note that we don't treat fatal
errors in the delayed thread as fatal errors in the
- main thread. Use of my_message will enable stored
- procedures continue handlers.
+ main thread. If delayed thread was killed, we don't
+ want to send "Server shutdown in progress" in the
+ INSERT THREAD.
*/
- my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(),
- MYF(0));
- }
- di->unlock();
+ if (di->thd.stmt_da->sql_errno() == ER_SERVER_SHUTDOWN)
+ my_message(ER_QUERY_INTERRUPTED, ER(ER_QUERY_INTERRUPTED), MYF(0));
+ else
+ my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(),
+ MYF(0));
+ }
+ di->unlock();
goto end_create;
}
- if (thd->killed)
- {
- di->unlock();
- goto end_create;
- }
pthread_mutex_lock(&LOCK_delayed_insert);
delayed_threads.append(di);
pthread_mutex_unlock(&LOCK_delayed_insert);
@@ -2061,7 +2065,11 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error;
if (dead)
{
- my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0));
+ /* Don't copy over "Server shutdown in progress". */
+ if (thd.stmt_da->sql_errno() == ER_SERVER_SHUTDOWN)
+ my_message(ER_QUERY_INTERRUPTED, ER(ER_QUERY_INTERRUPTED), MYF(0));
+ else
+ my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0));
goto error;
}
}
@@ -2412,7 +2420,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
for (;;)
{
- if (thd->killed == THD::KILL_CONNECTION)
+ if (thd->killed)
{
uint lock_count;
/*
@@ -2474,7 +2482,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
}
thd_proc_info(&(di->thd), 0);
- if (di->tables_in_use && ! thd->lock)
+ if (di->tables_in_use && ! thd->lock && !thd->killed)
{
bool need_reopen;
/*
@@ -2491,14 +2499,15 @@ pthread_handler_t handle_delayed_insert(void *arg)
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
&need_reopen)))
{
- if (need_reopen)
+ if (need_reopen && !thd->killed)
{
/*
We were waiting to obtain TL_WRITE_DELAYED (probably due to
someone having or requesting TL_WRITE_ALLOW_READ) and got
aborted. Try to reopen table and if it fails die.
*/
- close_thread_tables(thd);
+ TABLE_LIST *tl_ptr = &di->table_list;
+ close_tables_for_reopen(thd, &tl_ptr);
di->table= 0;
if (di->open_and_lock_table())
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index c49b22d23bd..7ea5c81c52b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -197,6 +197,8 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_CREATE_TRIGGER]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_TRIGGER]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
@@ -221,8 +223,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE;
- sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE |
- CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
@@ -237,34 +238,35 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
- sql_command_flags[SQLCOM_SHOW_NEW_MASTER]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_BINLOGS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_NEW_MASTER]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_BINLOGS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_STORAGE_ENGINES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_AUTHORS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_AUTHORS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CONTRIBUTORS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_PRIVILEGES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
- sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
+ sql_command_flags[SQLCOM_SHOW_PRIVILEGES]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
+ sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
- sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
CF_SHOW_TABLE_COMMAND |
@@ -273,37 +275,52 @@ void init_update_queries(void)
CF_SHOW_TABLE_COMMAND |
CF_REEXECUTION_FRAGILE);
+
+ sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_DROP_FUNCTION]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_DROP_PROCEDURE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_ALTER_PROCEDURE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_ALTER_FUNCTION]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_INSTALL_PLUGIN]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]= CF_CHANGES_DATA;
+
/*
The following is used to preserver CF_ROW_COUNT during the
a CALL or EXECUTE statement, so the value generated by the
last called (or executed) statement is preserved.
See mysql_execute_command() for how CF_ROW_COUNT is used.
*/
- sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT | CF_REEXECUTION_FRAGILE;
- sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
+ sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
/*
The following admin table operations are allowed
on log tables.
*/
- sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND |
- CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_OPTIMIZE]= CF_WRITE_LOGS_COMMAND |
- CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND |
- CF_AUTO_COMMIT_TRANS;
-
- sql_command_flags[SQLCOM_CREATE_USER]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_DROP_USER]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_RENAME_USER]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_REVOKE]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_GRANT]= CF_AUTO_COMMIT_TRANS;
-
- sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_ALTER_PROCEDURE]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_ALTER_FUNCTION]= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_OPTIMIZE]|= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
+
+ sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_REVOKE]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_GRANT]|= CF_AUTO_COMMIT_TRANS;
+
+ sql_command_flags[SQLCOM_CREATE_PROCEDURE]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_CREATE_SPFUNCTION]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_ALTER_PROCEDURE]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_ALTER_FUNCTION]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_PRELOAD_KEYS]= CF_AUTO_COMMIT_TRANS;
@@ -1745,7 +1762,6 @@ int
mysql_execute_command(THD *thd)
{
int res= FALSE;
- bool need_start_waiting= FALSE; // have protection against global read lock
int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
@@ -2022,7 +2038,7 @@ mysql_execute_command(THD *thd)
break;
if (!thd->locked_tables_mode && lex->protect_against_global_read_lock &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ wait_if_global_read_lock(thd, 0, 1))
break;
res= execute_sqlcom_select(thd, all_tables);
@@ -2292,10 +2308,9 @@ case SQLCOM_PREPARE:
read lock when it succeeds. This needs to be released by
start_waiting_global_read_lock(). We protect the normal CREATE
TABLE in the same way. That way we avoid that a new table is
- created during a gobal read lock.
+ created during a global read lock.
*/
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
goto end_with_restore_list;
@@ -2311,6 +2326,12 @@ case SQLCOM_PREPARE:
thd->work_part_info= part_info;
}
#endif
+
+ /*
+ Close any open handlers for the table
+ */
+ mysql_ha_rm_tables(thd, create_table);
+
if (select_lex->item_list.elements) // With select
{
select_result *result;
@@ -2594,8 +2615,7 @@ end_with_restore_list:
"INDEX DIRECTORY");
create_info.data_file_name= create_info.index_file_name= NULL;
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
break;
@@ -2829,8 +2849,7 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (update_precheck(thd, all_tables))
break;
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
goto error;
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
@@ -2868,7 +2887,7 @@ end_with_restore_list:
*/
if (!thd->locked_tables_mode &&
lex->sql_command == SQLCOM_UPDATE_MULTI &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ wait_if_global_read_lock(thd, 0, 1))
goto error;
res= mysql_multi_update_prepare(thd);
@@ -2970,8 +2989,7 @@ end_with_restore_list:
if ((res= insert_precheck(thd, all_tables)))
break;
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
break;
@@ -3010,8 +3028,7 @@ end_with_restore_list:
unit->set_limit(select_lex);
- if (! thd->locked_tables_mode &&
- ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
break;
@@ -3081,7 +3098,7 @@ end_with_restore_list:
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
- if (!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (wait_if_global_read_lock(thd, 0, 1))
goto error;
res= mysql_truncate(thd, first_table, 0);
break;
@@ -3093,8 +3110,7 @@ end_with_restore_list:
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
break;
@@ -3114,8 +3130,7 @@ end_with_restore_list:
(TABLE_LIST *)thd->lex->auxiliary_table_list.first;
multi_delete *del_result;
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
{
res= 1;
break;
@@ -3259,8 +3274,7 @@ end_with_restore_list:
if (check_one_table_access(thd, privilege, all_tables))
goto error;
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
goto error;
res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
@@ -3334,7 +3348,7 @@ end_with_restore_list:
FALSE, UINT_MAX, FALSE))
goto error;
if (lex->protect_against_global_read_lock &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ wait_if_global_read_lock(thd, 0, 1))
goto error;
init_mdl_requests(all_tables);
@@ -4552,7 +4566,7 @@ error:
res= TRUE;
finish:
- if (need_start_waiting)
+ if (thd->global_read_lock_protection > 0)
{
/*
Release the protection against the global read lock and wake
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 42d688542b5..44a0d21580f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1780,16 +1780,16 @@ void write_bin_log(THD *thd, bool clear_error,
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
my_bool drop_temporary)
{
- bool error= FALSE, need_start_waiting= FALSE;
+ bool error;
Drop_table_error_handler err_handler(thd->get_internal_handler());
+
DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */
if (!drop_temporary)
{
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(TRUE);
}
@@ -1797,8 +1797,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
thd->pop_internal_handler();
-
- if (need_start_waiting)
+ if (thd->global_read_lock_protection > 0)
start_waiting_global_read_lock(thd);
if (error)
@@ -4549,6 +4548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
char table_name[NAME_LEN*2+2];
char* db = table->db;
bool fatal_error=0;
+ bool open_error;
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
@@ -4576,12 +4576,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE;
- open_and_lock_tables_derived(thd, table, TRUE,
- MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
+ open_error= open_and_lock_tables_derived(thd, table, TRUE,
+ MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
thd->no_warnings_for_error= 0;
table->next_global= save_next_global;
table->next_local= save_next_local;
thd->open_options&= ~extra_open_options;
+ /*
+ Under locked tables, we know that the table can be opened,
+ so any errors opening the table are logical errors.
+ In these cases it does not make sense to try to repair.
+ */
+ if (open_error && thd->locked_tables_mode)
+ {
+ result_code= HA_ADMIN_FAILED;
+ goto send_result;
+ }
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->table)
{
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 08d0dacd8e8..823dca5d93f 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -328,7 +328,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
TABLE *table;
bool result= TRUE;
String stmt_query;
- bool need_start_waiting= FALSE;
bool lock_upgrade_done= FALSE;
MDL_ticket *mdl_ticket= NULL;
@@ -386,8 +385,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
LOCK_open is not enough because global read lock is held without holding
LOCK_open).
*/
- if (!thd->locked_tables_mode &&
- !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(TRUE);
if (!create)
@@ -521,7 +519,7 @@ end:
if (thd->locked_tables_mode && tables && lock_upgrade_done)
mdl_ticket->downgrade_exclusive_lock();
- if (need_start_waiting)
+ if (thd->global_read_lock_protection > 0)
start_waiting_global_read_lock(thd);
if (!result)