Merge from mysql-5.5-runtime to mysql-5.5-bugfixing.
This commit is contained in:
commit
39ac44d660
@ -997,6 +997,7 @@ libmysqld/.deps/sql_cursor.Po
|
||||
libmysqld/.deps/sql_db.Po
|
||||
libmysqld/.deps/sql_delete.Po
|
||||
libmysqld/.deps/sql_truncate.Po
|
||||
libmysqld/.deps/sql_reload.Po
|
||||
libmysqld/.deps/datadict.Po
|
||||
libmysqld/.deps/sql_derived.Po
|
||||
libmysqld/.deps/sql_do.Po
|
||||
@ -1175,6 +1176,7 @@ libmysqld/sql_cursor.h
|
||||
libmysqld/sql_db.cc
|
||||
libmysqld/sql_delete.cc
|
||||
libmysqld/sql_truncate.cc
|
||||
libmysqld/sql_reload.cc
|
||||
libmysqld/datadict.cc
|
||||
libmysqld/sql_derived.cc
|
||||
libmysqld/sql_do.cc
|
||||
@ -2067,6 +2069,7 @@ sql/.deps/sql_cursor.Po
|
||||
sql/.deps/sql_db.Po
|
||||
sql/.deps/sql_delete.Po
|
||||
sql/.deps/sql_truncate.Po
|
||||
sql/.deps/sql_reload.Po
|
||||
sql/.deps/datadict.Po
|
||||
sql/.deps/sql_derived.Po
|
||||
sql/.deps/sql_do.Po
|
||||
|
@ -782,7 +782,7 @@ dnl Emits shell script for checking configure arguments
|
||||
dnl Arguments to this macro is default value for selected plugins
|
||||
|
||||
AC_DEFUN([_MYSQL_CHECK_PLUGIN_ARGS],[
|
||||
__MYSQL_CHECK_PLUGIN_ARGS(m4_default([$1], [none]))
|
||||
__MYSQL_CHECK_PLUGIN_ARGS(m4_default([$1], [default]))
|
||||
])
|
||||
|
||||
AC_DEFUN([__MYSQL_CHECK_PLUGIN_ARGS],[
|
||||
|
@ -2606,7 +2606,7 @@ MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
|
||||
|
||||
dnl -- ndbcluster requires partition to be enabled
|
||||
|
||||
MYSQL_CONFIGURE_PLUGINS([none])
|
||||
MYSQL_CONFIGURE_PLUGINS([default])
|
||||
|
||||
# Only build client code?
|
||||
AC_ARG_WITH(server,
|
||||
|
@ -601,6 +601,8 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);
|
||||
#define rw_trywrlock(A) my_rw_trywrlock((A))
|
||||
#define rw_unlock(A) my_rw_unlock((A))
|
||||
#define rwlock_destroy(A) my_rw_destroy((A))
|
||||
#define rw_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A))
|
||||
#define rw_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A))
|
||||
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
|
||||
|
||||
|
||||
@ -624,6 +626,8 @@ extern int rw_pr_init(rw_pr_lock_t *);
|
||||
#define rw_pr_trywrlock(A) pthread_rwlock_trywrlock(A)
|
||||
#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
|
||||
#define rw_pr_destroy(A) pthread_rwlock_destroy(A)
|
||||
#define rw_pr_lock_assert_write_owner(A)
|
||||
#define rw_pr_lock_assert_not_write_owner(A)
|
||||
#else
|
||||
/* Otherwise we have to use our own implementation of read/write locks. */
|
||||
#define NEED_MY_RW_LOCK 1
|
||||
@ -636,6 +640,8 @@ extern int rw_pr_init(struct st_my_rw_lock_t *);
|
||||
#define rw_pr_trywrlock(A) my_rw_trywrlock((A))
|
||||
#define rw_pr_unlock(A) my_rw_unlock((A))
|
||||
#define rw_pr_destroy(A) my_rw_destroy((A))
|
||||
#define rw_pr_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A))
|
||||
#define rw_pr_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A))
|
||||
#endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */
|
||||
|
||||
|
||||
@ -651,6 +657,9 @@ typedef struct st_my_rw_lock_t {
|
||||
int state; /* -1:writer,0:free,>0:readers */
|
||||
int waiters; /* number of waiting writers */
|
||||
my_bool prefer_readers;
|
||||
#ifdef SAFE_MUTEX
|
||||
pthread_t write_thread;
|
||||
#endif
|
||||
} my_rw_lock_t;
|
||||
|
||||
extern int my_rw_init(my_rw_lock_t *, my_bool *);
|
||||
@ -660,6 +669,17 @@ extern int my_rw_wrlock(my_rw_lock_t *);
|
||||
extern int my_rw_unlock(my_rw_lock_t *);
|
||||
extern int my_rw_tryrdlock(my_rw_lock_t *);
|
||||
extern int my_rw_trywrlock(my_rw_lock_t *);
|
||||
#ifdef SAFE_MUTEX
|
||||
#define my_rw_lock_assert_write_owner(A) \
|
||||
DBUG_ASSERT((A)->state == -1 && pthread_equal(pthread_self(), \
|
||||
(A)->write_thread))
|
||||
#define my_rw_lock_assert_not_write_owner(A) \
|
||||
DBUG_ASSERT((A)->state >= 0 || ! pthread_equal(pthread_self(), \
|
||||
(A)->write_thread))
|
||||
#else
|
||||
#define my_rw_lock_assert_write_owner(A)
|
||||
#define my_rw_lock_assert_not_write_owner(A)
|
||||
#endif
|
||||
#endif /* NEED_MY_RW_LOCK */
|
||||
|
||||
|
||||
|
@ -215,6 +215,14 @@ typedef struct st_mysql_cond mysql_cond_t;
|
||||
#define mysql_mutex_assert_not_owner(M) \
|
||||
safe_mutex_assert_not_owner(&(M)->m_mutex)
|
||||
|
||||
/** Wrappers for instrumented prlock objects. */
|
||||
|
||||
#define mysql_prlock_assert_write_owner(M) \
|
||||
rw_pr_lock_assert_write_owner(&(M)->m_prlock)
|
||||
|
||||
#define mysql_prlock_assert_not_write_owner(M) \
|
||||
rw_pr_lock_assert_not_write_owner(&(M)->m_prlock)
|
||||
|
||||
/**
|
||||
@def mysql_mutex_init(K, M, A)
|
||||
Instrumented mutex_init.
|
||||
|
@ -64,7 +64,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
||||
../sql/sql_db.cc ../sql/sql_delete.cc ../sql/sql_derived.cc
|
||||
../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.cc
|
||||
../sql/sql_help.cc ../sql/sql_insert.cc ../sql/datadict.cc
|
||||
../sql/sql_admin.cc ../sql/sql_truncate.cc
|
||||
../sql/sql_admin.cc ../sql/sql_truncate.cc ../sql/sql_reload.cc
|
||||
../sql/sql_lex.cc ../sql/keycaches.cc
|
||||
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
|
||||
../sql/sql_binlog.cc ../sql/sql_manager.cc
|
||||
|
@ -64,6 +64,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
||||
opt_sum.cc procedure.cc records.cc sql_acl.cc \
|
||||
sql_load.cc discover.cc sql_locale.cc \
|
||||
sql_profile.cc sql_admin.cc sql_truncate.cc datadict.cc \
|
||||
sql_reload.cc \
|
||||
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
|
||||
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
|
||||
sql_lex.cc sql_list.cc sql_manager.cc \
|
||||
|
@ -153,7 +153,7 @@ connection master;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE info = "RENAME TABLE t1 TO t3, t2 TO t1" and
|
||||
state = "Waiting for table";
|
||||
state = "Waiting for table metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
COMMIT;
|
||||
|
@ -43,7 +43,8 @@ connection default;
|
||||
# of our statement.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "insert into $table (i) values (0)";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "insert into $table (i) values (0)";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--disable_result_log
|
||||
|
@ -523,7 +523,7 @@ connection waiter;
|
||||
--echo connection: waiter
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
where state = "Waiting for table flush";
|
||||
--source include/wait_condition.inc
|
||||
connection default;
|
||||
--echo connection: default
|
||||
@ -557,7 +557,8 @@ connection waiter;
|
||||
--echo connection: waiter
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "rename table t1 to t0";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "rename table t1 to t0";
|
||||
--source include/wait_condition.inc
|
||||
connection default;
|
||||
--echo connection: default
|
||||
@ -743,7 +744,8 @@ send alter table t1 engine=memory;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 engine=memory";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 engine=memory";
|
||||
--source include/wait_condition.inc
|
||||
connection default;
|
||||
--error ER_ILLEGAL_HA
|
||||
@ -764,7 +766,8 @@ send alter table t1 engine=memory;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 engine=memory";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 engine=memory";
|
||||
--source include/wait_condition.inc
|
||||
connection default;
|
||||
--echo # Since S metadata lock was already acquired at HANDLER OPEN time
|
||||
@ -1024,7 +1027,9 @@ connection con1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop table t1' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t1';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
@ -1055,7 +1060,9 @@ connection con1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waiting for 'drop table t1' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t1';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
@ -1097,7 +1104,8 @@ send rename table t0 to t3, t1 to t0, t3 to t1;
|
||||
connection con1;
|
||||
--echo # Waiting for 'rename table ...' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='rename table t0 to t3, t1 to t0, t3 to t1';
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='rename table t0 to t3, t1 to t0, t3 to t1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
@ -1137,7 +1145,9 @@ connection con2;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
--echo # Waiting for 'drop table t2' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t2';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
@ -1146,7 +1156,9 @@ send select * from t2;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
--echo # Waiting for 'select * from t2' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='select * from t2';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='select * from t2';
|
||||
unlock tables;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
@ -1190,10 +1202,14 @@ connection default;
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waiting for 'drop table t1' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t1';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Waiting for 'drop table t2' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t2';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
||||
--echo # after ROLLBACK TO SAVEPOINT
|
||||
@ -1255,10 +1271,14 @@ connection default;
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waiting for 'drop table t1' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t1';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Waiting for 'drop table t2' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t2';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
||||
--echo # after ROLLBACK TO SAVEPOINT
|
||||
@ -1314,7 +1334,9 @@ drop table t1, t2;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waiting for 'drop table t3' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t3';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t3';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
--echo # lock.
|
||||
@ -1348,7 +1370,9 @@ send drop table t2;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waiting for 'drop table t2' to get blocked...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t2';
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='drop table t2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
@ -1400,7 +1424,8 @@ connection con2;
|
||||
--echo # has read from the table commits.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "lock tables t1 write";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "lock tables t1 write";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # --> connection default
|
||||
@ -1427,7 +1452,8 @@ connection con1;
|
||||
--echo # Waiting for 'handler t1 read a next' to get blocked...
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "handler t1 read a next";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "handler t1 read a next";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # The below 'drop table t1' should be able to proceed without
|
||||
|
@ -1,10 +0,0 @@
|
||||
disable_query_log;
|
||||
disable_result_log;
|
||||
set @have_thread_concurrency=0;
|
||||
select @have_thread_concurrency:=1 from information_schema.global_variables where variable_name='thread_concurrency';
|
||||
if (`select @have_thread_concurrency = 0`)
|
||||
{
|
||||
skip Need @@thread_concurrency;
|
||||
}
|
||||
enable_result_log;
|
||||
enable_query_log;
|
@ -1580,7 +1580,7 @@ connect (con1, localhost, root,,);
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table' AND info='TRUNCATE TABLE t1';
|
||||
WHERE state='Waiting for table metadata lock' AND info='TRUNCATE TABLE t1';
|
||||
--source include/wait_condition.inc
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
ROLLBACK;
|
||||
|
@ -116,3 +116,22 @@ OK: create event: database does not exist
|
||||
delete from t1;
|
||||
commit work;
|
||||
drop database events_test;
|
||||
#
|
||||
# Bug#54105 assert in MDL_context::release_locks_stored_before
|
||||
#
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP EVENT IF EXISTS e1;
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
CREATE TABLE t2 (a INT);
|
||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SAVEPOINT A;
|
||||
SHOW CREATE EVENT e1;
|
||||
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
|
||||
e1 SYSTEM CREATE DEFINER=`root`@`localhost` EVENT `e1` ON SCHEDULE EVERY 1 DAY STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
SELECT * FROM t2;
|
||||
a
|
||||
ROLLBACK WORK TO SAVEPOINT A;
|
||||
DROP TABLE t1, t2;
|
||||
|
@ -205,6 +205,51 @@ a
|
||||
insert into t2 (a) values (3);
|
||||
# --> connection default;
|
||||
unlock tables;
|
||||
#
|
||||
# Check that "FLUSH TABLES <list> WITH READ LOCK" is
|
||||
# compatible with active "FLUSH TABLES WITH READ LOCK".
|
||||
# Vice versa it is not true, since tables read-locked by
|
||||
# "FLUSH TABLES <list> WITH READ LOCK" can't be flushed.
|
||||
flush tables with read lock;
|
||||
# --> connection con1;
|
||||
flush table t1 with read lock;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
unlock tables;
|
||||
# --> connection default;
|
||||
unlock tables;
|
||||
#
|
||||
# Check that FLUSH TABLES t1 WITH READ LOCK
|
||||
# does not conflict with an existing FLUSH TABLES t2
|
||||
# WITH READ LOCK.
|
||||
#
|
||||
flush table t1 with read lock;
|
||||
# --> connection con1
|
||||
flush table t2 with read lock;
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
unlock tables;
|
||||
#
|
||||
# Check that FLUSH TABLES t1 WITH READ LOCK
|
||||
# does not conflict with SET GLOBAL read_only=1.
|
||||
#
|
||||
set global read_only=1;
|
||||
# connection con1
|
||||
flush table t1 with read lock;
|
||||
unlock tables;
|
||||
# connection default
|
||||
set global read_only=0;
|
||||
#
|
||||
# Check that it's possible to read-lock
|
||||
# tables locked with FLUSH TABLE <list> WITH READ LOCK.
|
||||
#
|
||||
flush tables t1, t2 with read lock;
|
||||
# connection con1
|
||||
lock table t1 read, t2 read;
|
||||
unlock tables;
|
||||
# connection default
|
||||
unlock tables;
|
||||
# --> connection con1
|
||||
drop table t1, t2, t3;
|
||||
#
|
||||
@ -234,3 +279,97 @@ drop temporary table v1;
|
||||
unlock tables;
|
||||
drop view v2, v3;
|
||||
drop table t1, v1;
|
||||
#
|
||||
# FLUSH TABLES <list> WITH READ LOCK and HANDLER
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3);
|
||||
handler t1 open;
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
handler t1 read a next;
|
||||
a
|
||||
2
|
||||
flush tables t1 with read lock;
|
||||
handler t1 read a next;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
#
|
||||
# Sic: lost handler position.
|
||||
#
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
handler t1 close;
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#52117 Pending FLUSH TALBES <list> aborts
|
||||
# transactions unnecessarily.
|
||||
#
|
||||
drop table if exists t1;
|
||||
# --> conection default
|
||||
create table t1 (a int);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
# --> connection con1
|
||||
#
|
||||
# Issue a LOCK TABLE t1 READ. We could use HANDLER t1 OPEN
|
||||
# or a long-running select -- anything that
|
||||
# prevents FLUSH TABLE t1 from immediate completion would do.
|
||||
#
|
||||
lock table t1 read;
|
||||
# --> connection con2
|
||||
#
|
||||
# FLUSH TABLE expels the table definition from the cache.
|
||||
# Sending 'flush table t1'...
|
||||
flush table t1;
|
||||
# --> connection default
|
||||
# Let flush table sync in.
|
||||
select * from t1;
|
||||
# --> connection con1
|
||||
select * from t1;
|
||||
a
|
||||
unlock tables;
|
||||
# --> connection con2
|
||||
# Reaping 'flush table t1'...
|
||||
# --> connection default
|
||||
# Reaping 'select * from t1'...
|
||||
a
|
||||
commit;
|
||||
#
|
||||
# Repeat the same test but with FLUSH TABLES
|
||||
#
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
# --> connection con1
|
||||
#
|
||||
# Issue a LOCK TABLE t1 READ.
|
||||
#
|
||||
lock table t1 read;
|
||||
# --> connection con2
|
||||
#
|
||||
# FLUSH TABLES expels the table definition from the cache.
|
||||
# Sending 'flush tables'...
|
||||
flush tables;
|
||||
# --> connection default
|
||||
# Let flush table sync in.
|
||||
select * from t1;
|
||||
# --> connection con1
|
||||
select * from t1;
|
||||
a
|
||||
unlock tables;
|
||||
# --> connection con2
|
||||
# Reaping 'flush tables'...
|
||||
# --> connection default
|
||||
# Reaping 'select * from t1'...
|
||||
a
|
||||
commit;
|
||||
# Cleanup
|
||||
# --> connection con1
|
||||
# --> connection con2
|
||||
# --> connection default
|
||||
drop table t1;
|
||||
|
@ -89,3 +89,15 @@ UNIQUE_CONSTRAINT_NAME
|
||||
NULL
|
||||
drop table t2;
|
||||
set foreign_key_checks = 1;
|
||||
#
|
||||
# Bug#55973 Assertion `thd->transaction.stmt.is_empty()'
|
||||
# on CREATE TABLE .. SELECT I_S.PART
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
CREATE VIEW v1 AS SELECT 1;
|
||||
CREATE TABLE t1 engine = InnoDB AS
|
||||
SELECT * FROM information_schema.partitions
|
||||
WHERE table_schema= 'test' AND table_name= 'v1';
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
|
@ -2034,6 +2034,155 @@ set debug_sync='now SIGNAL go2';
|
||||
# Switching to connection 'default'.
|
||||
# Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK.
|
||||
drop table t1;
|
||||
#
|
||||
# Now, test for a situation in which deadlock involves waiting not
|
||||
# only in MDL subsystem but also for TDC. Such deadlocks should be
|
||||
# successfully detected. If possible, they should be resolved without
|
||||
# resorting to ER_LOCK_DEADLOCK error.
|
||||
#
|
||||
create table t1(i int);
|
||||
create table t2(j int);
|
||||
#
|
||||
# First, let us check how we handle a simple scenario involving
|
||||
# waits in MDL and TDC.
|
||||
#
|
||||
set debug_sync= 'RESET';
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Start a statement, which will acquire SR metadata lock on t1, open it
|
||||
# and then stop, before trying to acquire SW lock on t2 and opening it.
|
||||
set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go';
|
||||
# Sending:
|
||||
select * from t1 where i in (select j from t2 for update);
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
# Wait till the above SELECT stops.
|
||||
set debug_sync='now WAIT_FOR parked';
|
||||
# The below FLUSH TABLES WITH READ LOCK should acquire
|
||||
# SNW locks on t1 and t2 and wait till SELECT closes t1.
|
||||
# Sending:
|
||||
flush tables t1, t2 with read lock;
|
||||
# Switching to connection 'deadlock_con3'.
|
||||
# Wait until FLUSH TABLES WITH t1, t2 READ LOCK starts waiting
|
||||
# for SELECT to close t1.
|
||||
# Resume SELECT, so it tries to acquire SW lock on t1 and blocks,
|
||||
# creating a deadlock. This deadlock should be detected and resolved
|
||||
# by backing-off SELECT. As a result FTWRL should be able to finish.
|
||||
set debug_sync='now SIGNAL go';
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
# Reap FLUSH TABLES WITH READ LOCK.
|
||||
unlock tables;
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Reap SELECT.
|
||||
i
|
||||
#
|
||||
# The same scenario with a slightly different order of events
|
||||
# which emphasizes that setting correct deadlock detector weights
|
||||
# for flush waits is important.
|
||||
#
|
||||
set debug_sync= 'RESET';
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
set debug_sync='flush_tables_with_read_lock_after_acquire_locks SIGNAL parked WAIT_FOR go';
|
||||
# The below FLUSH TABLES WITH READ LOCK should acquire
|
||||
# SNW locks on t1 and t2 and wait on debug sync point.
|
||||
# Sending:
|
||||
flush tables t1, t2 with read lock;
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Wait till FLUSH TABLE WITH READ LOCK stops.
|
||||
set debug_sync='now WAIT_FOR parked';
|
||||
# Start statement which will acquire SR metadata lock on t1, open
|
||||
# it and then will block while trying to acquire SW lock on t2.
|
||||
# Sending:
|
||||
select * from t1 where i in (select j from t2 for update);
|
||||
# Switching to connection 'deadlock_con3'.
|
||||
# Wait till the above SELECT blocks.
|
||||
# Resume FLUSH TABLES, so it tries to flush t1, thus creating
|
||||
# a deadlock. This deadlock should be detected and resolved by
|
||||
# backing-off SELECT. As a result FTWRL should be able to finish.
|
||||
set debug_sync='now SIGNAL go';
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
# Reap FLUSH TABLES WITH READ LOCK.
|
||||
unlock tables;
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Reap SELECT.
|
||||
i
|
||||
#
|
||||
# Now a more complex scenario involving two connections
|
||||
# waiting for MDL and one for TDC.
|
||||
#
|
||||
set debug_sync= 'RESET';
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Start a statement which will acquire SR metadata lock on t2, open it
|
||||
# and then stop, before trying to acquire SR on t1 and opening it.
|
||||
set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go';
|
||||
# Sending:
|
||||
select * from t2, t1;
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
# Wait till the above SELECT stops.
|
||||
set debug_sync='now WAIT_FOR parked';
|
||||
# The below FLUSH TABLES WITH READ LOCK should acquire
|
||||
# SNW locks on t2 and wait till SELECT closes t2.
|
||||
# Sending:
|
||||
flush tables t2 with read lock;
|
||||
# Switching to connection 'deadlock_con3'.
|
||||
# Wait until FLUSH TABLES WITH READ LOCK starts waiting
|
||||
# for SELECT to close t2.
|
||||
# The below DROP TABLES should acquire X lock on t1 and start
|
||||
# waiting for X lock on t2.
|
||||
# Sending:
|
||||
drop tables t1, t2;
|
||||
# Switching to connection 'default'.
|
||||
# Wait until DROP TABLES starts waiting for X lock on t2.
|
||||
# Resume SELECT, so it tries to acquire SR lock on t1 and blocks,
|
||||
# creating a deadlock. This deadlock should be detected and resolved
|
||||
# by backing-off SELECT. As a result, FTWRL should be able to finish.
|
||||
set debug_sync='now SIGNAL go';
|
||||
# Switching to connection 'deadlock_con2'.
|
||||
# Reap FLUSH TABLES WITH READ LOCK.
|
||||
# Unblock DROP TABLES.
|
||||
unlock tables;
|
||||
# Switching to connection 'deadlock_con3'.
|
||||
# Reap DROP TABLES.
|
||||
# Switching to connection 'deadlock_con1'.
|
||||
# Reap SELECT. It should emit error about missing table.
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
# Switching to connection 'default'.
|
||||
set debug_sync= 'RESET';
|
||||
#
|
||||
# Test for a scenario in which FLUSH TABLES <list> WITH READ LOCK
|
||||
# used to erroneously release metadata locks.
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
set debug_sync= 'RESET';
|
||||
create table t1(i int);
|
||||
create table t2(j int);
|
||||
# Switching to connection 'con2'.
|
||||
set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go';
|
||||
# The below FLUSH TABLES <list> WITH READ LOCK should acquire
|
||||
# SNW locks on t1 and t2, open table t1 and block on the debug
|
||||
# sync point.
|
||||
# Sending:
|
||||
flush tables t1, t2 with read lock;
|
||||
# Switching to connection 'con1'.
|
||||
# Wait till FLUSH TABLES <list> WITH READ LOCK stops.
|
||||
set debug_sync='now WAIT_FOR parked';
|
||||
# Start a statement which will flush all tables and thus
|
||||
# invalidate table t1 open by FLUSH TABLES <list> WITH READ LOCK.
|
||||
# Sending:
|
||||
flush tables;
|
||||
# Switching to connection 'default'.
|
||||
# Wait till the above FLUSH TABLES blocks.
|
||||
# Resume FLUSH TABLES <list> WITH READ LOCK, so it tries to open t2
|
||||
# discovers that its t1 is obsolete and tries to reopen all tables.
|
||||
# Such reopen should not cause releasing of SNW metadata locks
|
||||
# which would result in assertion failures.
|
||||
set debug_sync='now SIGNAL go';
|
||||
# Switching to connection 'con2'.
|
||||
# Reap FLUSH TABLES <list> WITH READ LOCK.
|
||||
unlock tables;
|
||||
# Switching to connection 'con1'.
|
||||
# Reap FLUSH TABLES.
|
||||
# Clean-up.
|
||||
# Switching to connection 'default'.
|
||||
drop tables t1, t2;
|
||||
set debug_sync= 'RESET';
|
||||
#
|
||||
# Test for bug #46748 "Assertion in MDL_context::wait_for_locks()
|
||||
|
@ -701,6 +701,7 @@ drop table t1,t2,t3,t4;
|
||||
set query_cache_wlock_invalidate=1;
|
||||
create table t1 (a int not null);
|
||||
create table t2 (a int not null);
|
||||
create view v1 as select * from t1;
|
||||
select * from t1;
|
||||
a
|
||||
select * from t2;
|
||||
@ -713,6 +714,17 @@ show status like "Qcache_queries_in_cache";
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 1
|
||||
unlock table;
|
||||
select * from t1;
|
||||
a
|
||||
show status like "Qcache_queries_in_cache";
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 2
|
||||
lock table v1 write;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 2
|
||||
unlock table;
|
||||
drop view v1;
|
||||
drop table t1,t2;
|
||||
set query_cache_wlock_invalidate=default;
|
||||
CREATE TABLE t1 (id INT PRIMARY KEY);
|
||||
@ -853,7 +865,7 @@ Variable_name Value
|
||||
Qcache_queries_in_cache 0
|
||||
show status like "Qcache_inserts";
|
||||
Variable_name Value
|
||||
Qcache_inserts 18
|
||||
Qcache_inserts 19
|
||||
show status like "Qcache_hits";
|
||||
Variable_name Value
|
||||
Qcache_hits 6
|
||||
@ -866,7 +878,7 @@ Variable_name Value
|
||||
Qcache_queries_in_cache 1
|
||||
show status like "Qcache_inserts";
|
||||
Variable_name Value
|
||||
Qcache_inserts 19
|
||||
Qcache_inserts 20
|
||||
show status like "Qcache_hits";
|
||||
Variable_name Value
|
||||
Qcache_hits 7
|
||||
|
@ -16,21 +16,19 @@ drop schema foo;
|
||||
# Bug #48940 MDL deadlocks against mysql_rm_db
|
||||
#
|
||||
DROP SCHEMA IF EXISTS schema1;
|
||||
DROP SCHEMA IF EXISTS schema2;
|
||||
# Connection default
|
||||
CREATE SCHEMA schema1;
|
||||
CREATE SCHEMA schema2;
|
||||
CREATE TABLE schema1.t1 (a INT);
|
||||
SET autocommit= FALSE;
|
||||
INSERT INTO schema1.t1 VALUES (1);
|
||||
# Connection 2
|
||||
DROP SCHEMA schema1;
|
||||
# Connection default
|
||||
ALTER SCHEMA schema2 DEFAULT CHARACTER SET utf8;
|
||||
ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8;
|
||||
Got one of the listed errors
|
||||
SET autocommit= TRUE;
|
||||
# Connection 2
|
||||
# Connection default
|
||||
DROP SCHEMA schema2;
|
||||
#
|
||||
# Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
|
||||
#
|
||||
|
@ -148,12 +148,12 @@ f1()
|
||||
# Sending 'drop procedure p1'...
|
||||
drop procedure p1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop procedure t1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -174,12 +174,12 @@ f1()
|
||||
# Sending 'create procedure p1'...
|
||||
create procedure p1() begin end;
|
||||
# --> connection con2
|
||||
# Waitng for 'create procedure t1' to get blocked on MDL lock...
|
||||
# Waiting for 'create procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -200,12 +200,12 @@ f1()
|
||||
# Sending 'alter procedure p1'...
|
||||
alter procedure p1 contains sql;
|
||||
# --> connection con2
|
||||
# Waitng for 'alter procedure t1' to get blocked on MDL lock...
|
||||
# Waiting for 'alter procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -226,12 +226,12 @@ f1()
|
||||
# Sending 'drop function f1'...
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -252,12 +252,12 @@ f1()
|
||||
# Sending 'create function f1'...
|
||||
create function f1() returns int return 2;
|
||||
# --> connection con2
|
||||
# Waitng for 'create function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'create function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -279,12 +279,12 @@ f1()
|
||||
# Sending 'alter function f1'...
|
||||
alter function f1 contains sql;
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'alter function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -360,7 +360,7 @@ insert into t1 (a) values (1);
|
||||
# Sending 'drop function f1'
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -379,7 +379,7 @@ a
|
||||
# Sending 'drop function f1'
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -403,7 +403,7 @@ a
|
||||
# Sending 'drop procedure p1'
|
||||
drop procedure p1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop procedure p1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop procedure p1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -424,7 +424,7 @@ insert into t1 (a) values (3);
|
||||
# Sending 'drop function f2'
|
||||
drop function f2;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f2' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -479,11 +479,11 @@ f2()
|
||||
# Sending 'drop function f1'...
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
# Sending 'drop function f2'...
|
||||
drop function f2;
|
||||
# --> connection default
|
||||
# Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
# Waiting for 'drop function f2' to get blocked on MDL lock...
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop function f2'...
|
||||
@ -537,10 +537,10 @@ f1()
|
||||
# Sending 'alter function f1 ...'...
|
||||
alter function f1 comment "comment";
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
# Waiting for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
# Sending 'call p1()'...
|
||||
call p1();
|
||||
# Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Waiting for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -573,7 +573,7 @@ f1()
|
||||
# Sending 'alter function f1 ...'...
|
||||
alter function f1 comment "comment";
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
# Waiting for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
#
|
||||
# We just mention p1() in the body of f2() to make
|
||||
# sure that p1() is prelocked for f2().
|
||||
@ -595,7 +595,7 @@ select f2() into @var;
|
||||
end|
|
||||
# Sending 'call p1()'...
|
||||
call p1();
|
||||
# Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Waiting for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
# --> connection con1
|
||||
@ -634,7 +634,7 @@ get_lock("30977", 0)
|
||||
# Sending 'select f3()'...
|
||||
select f3();
|
||||
# --> connection con1
|
||||
# Waitng for 'select f3()' to get blocked on the user level lock...
|
||||
# Waiting for 'select f3()' to get blocked on the user level lock...
|
||||
# Do something to change the cache version.
|
||||
create function f4() returns int return 4;
|
||||
drop function f4;
|
||||
|
@ -35,7 +35,7 @@ call bug9486();
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Sleep # NULL
|
||||
# root localhost test Query # Waiting for table update t1, t2 set val= 1 where id1=id2
|
||||
# root localhost test Query # Waiting for table metadata lock update t1, t2 set val= 1 where id1=id2
|
||||
# root localhost test Query # NULL show processlist
|
||||
# root localhost test Sleep # NULL
|
||||
unlock tables;
|
||||
|
@ -60,7 +60,7 @@ let $wait_condition=
|
||||
--echo # con1
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
||||
state = "Table lock" and info = "INSERT INTO t2 VALUES (3)";
|
||||
state = "Waiting for table level lock" and info = "INSERT INTO t2 VALUES (3)";
|
||||
--source include/wait_condition.inc
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
--connection con2
|
||||
|
@ -367,14 +367,14 @@ echo
|
||||
;
|
||||
connection default;
|
||||
echo
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table'.
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table metadata lock'.
|
||||
;
|
||||
let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table';
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
#
|
||||
# Expect to see the state 'Waiting for table' for the third connection because the SELECT
|
||||
# collides with the WRITE TABLE LOCK.
|
||||
# Expect to see the state 'Waiting for table metadata lock' for the third
|
||||
# connection because the SELECT collides with the WRITE TABLE LOCK.
|
||||
--replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
|
||||
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||
UNLOCK TABLES;
|
||||
@ -422,10 +422,10 @@ echo
|
||||
;
|
||||
connection default;
|
||||
echo
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table'.
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table metadata lock'.
|
||||
;
|
||||
let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table';
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
echo
|
||||
# Expect result:
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -87,7 +87,8 @@ connection con1;
|
||||
--echo # Wait until LOCK TABLE is blocked on SQL-level lock.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "lock table t1 write";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "lock table t1 write";
|
||||
--source include/wait_condition.inc
|
||||
--echo # We should be able to do UPDATEs and SELECTs within transaction.
|
||||
update t1 set x=1 where id = 0;
|
||||
|
@ -28,7 +28,8 @@ ALTER TABLE t1 TRUNCATE PARTITION pMax;
|
||||
--echo # con default
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE STATE = "Waiting for table" AND INFO = "ALTER TABLE t1 TRUNCATE PARTITION pMax";
|
||||
WHERE STATE = "Waiting for table metadata lock" AND
|
||||
INFO = "ALTER TABLE t1 TRUNCATE PARTITION pMax";
|
||||
--source include/wait_condition.inc
|
||||
--sorted_result
|
||||
SELECT * FROM t1;
|
||||
|
@ -40,12 +40,12 @@ wait/synch/cond/sql/COND_flush_thread_cache YES YES
|
||||
wait/synch/cond/sql/COND_global_read_lock YES YES
|
||||
wait/synch/cond/sql/COND_manager YES YES
|
||||
wait/synch/cond/sql/COND_queue_state YES YES
|
||||
wait/synch/cond/sql/COND_refresh YES YES
|
||||
wait/synch/cond/sql/COND_rpl_status YES YES
|
||||
wait/synch/cond/sql/COND_server_started YES YES
|
||||
wait/synch/cond/sql/COND_thread_cache YES YES
|
||||
wait/synch/cond/sql/COND_thread_count YES YES
|
||||
wait/synch/cond/sql/Delayed_insert::cond YES YES
|
||||
wait/synch/cond/sql/Delayed_insert::cond_client YES YES
|
||||
select * from performance_schema.SETUP_INSTRUMENTS
|
||||
where name='Wait';
|
||||
select * from performance_schema.SETUP_INSTRUMENTS
|
||||
|
@ -182,7 +182,7 @@ count(name)
|
||||
select count(name) from COND_INSTANCES
|
||||
where name like "wait/synch/cond/sql/COND_refresh";
|
||||
count(name)
|
||||
1
|
||||
0
|
||||
select count(name) from COND_INSTANCES
|
||||
where name like "wait/synch/cond/sql/COND_thread_count";
|
||||
count(name)
|
||||
|
@ -30,7 +30,7 @@ connection master1;
|
||||
connection master;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info = "DROP TABLE tt";
|
||||
WHERE state = "Waiting for table metadata lock" AND info = "DROP TABLE tt";
|
||||
--source include/wait_condition.inc
|
||||
ROLLBACK TO SAVEPOINT insert_statement;
|
||||
COMMIT;
|
||||
|
@ -655,7 +655,8 @@ connection master;
|
||||
connection master1;
|
||||
--echo # Waitng for 'insert into t1 ...' to get blocked on table lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='insert into t1 (a) values (f1())';
|
||||
where state='Waiting for table metadata lock' and
|
||||
info='insert into t1 (a) values (f1())';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Sending 'drop function f1'. It will wait till insert finishes.
|
||||
--send drop function f1;
|
||||
@ -663,7 +664,7 @@ where state='Waiting for table' and info='insert into t1 (a) values (f1())';
|
||||
connection default;
|
||||
--echo # Check that 'drop function f1' gets blocked.
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f1';
|
||||
where state='Waiting for stored function metadata lock' and info='drop function f1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Now let's let 'insert' go through...
|
||||
unlock tables;
|
||||
|
@ -56,7 +56,7 @@ let $wait_condition=
|
||||
connection master;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "drop view v1";
|
||||
where state = "Waiting for table metadata lock" and info = "drop view v1";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
select release_lock("lock_bg25144");
|
||||
@ -106,7 +106,7 @@ let $wait_condition=
|
||||
connection master;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter view v1 as select * from t2";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
rpl_ndb_stm_innodb : Bug#54850 2010-07-02 alik rpl_ndb.rpl_ndb_stm_innodb and rpl_ndb.rpl_ndb_2other fails
|
||||
rpl_ndb_2other : Bug#54850 2010-07-02 alik rpl_ndb.rpl_ndb_stm_innodb and rpl_ndb.rpl_ndb_2other fails
|
||||
rpl_ndb_row_implicit_commit_binlog : Bug#55849 2010-08-09 alik rpl_ndb.rpl_ndb_row_implicit_commit_binlog fails
|
||||
|
||||
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
|
||||
|
@ -1 +1 @@
|
||||
--innodb --loose-ndbcluster=OFF --log-slave-updates=0
|
||||
--innodb --loose-ndbcluster=OFF --log-slave-updates=0 --default-storage-engine=MyISAM
|
||||
|
1
mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-slave.opt
Normal file
1
mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-slave.opt
Normal file
@ -0,0 +1 @@
|
||||
--default-storage-engine=MyISAM
|
@ -37,9 +37,9 @@ INSERT INTO t1(name) VALUES('Record_7');
|
||||
connection default;
|
||||
## show processlist info and state ##
|
||||
SELECT state,info FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE state= "Table lock" AND info LIKE "INSERT INTO t1%";
|
||||
WHERE state= "Waiting for table level lock" AND info LIKE "INSERT INTO t1%";
|
||||
state info
|
||||
Table lock INSERT INTO t1(name) VALUES('Record_7')
|
||||
Waiting for table level lock INSERT INTO t1(name) VALUES('Record_7')
|
||||
## table contents befor UNLOCK ##
|
||||
SELECT * FROM t1;
|
||||
name
|
||||
|
@ -11,7 +11,6 @@ CREATE TABLE t1(id int, value varchar(10));
|
||||
INSERT INTO t1 VALUES(1, 'val1');
|
||||
INSERT INTO t1 VALUES(2, 'val2');
|
||||
INSERT INTO t1 VALUES(3, 'val3');
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
SET GLOBAL query_cache_size = 131072;
|
||||
FLUSHING CACHE
|
||||
SET GLOBAL query_cache_size = 0;
|
||||
@ -33,11 +32,11 @@ SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 1
|
||||
1 Expected
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
UNLOCK TABLES;
|
||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 1
|
||||
Qcache_queries_in_cache 0
|
||||
0 Expected
|
||||
'#----------------------------FN_DYNVARS_136_02-----------------------#'
|
||||
SELECT * FROM t1;
|
||||
@ -49,13 +48,12 @@ id value
|
||||
2 val2
|
||||
3 val3
|
||||
** Connection con0 **
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
** Connection con1 **
|
||||
** Asynchronous Execution **
|
||||
SELECT * FROM t1;
|
||||
** Connection con0 **
|
||||
wait until table is locked
|
||||
Timeout in wait_condition.inc for SELECT count(*) > 0 FROM information_schema.processlist WHERE state= 'Table lock'
|
||||
UNLOCK TABLES;
|
||||
** Connection con1 **
|
||||
** Asynchronous Result **
|
||||
@ -79,7 +77,7 @@ SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 1
|
||||
1 Expected
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
UNLOCK TABLES;
|
||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
Variable_name Value
|
||||
@ -102,7 +100,7 @@ id value
|
||||
2 val2
|
||||
3 val3
|
||||
** Connection con0 **
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
** Connection con1 **
|
||||
** Should not be blocked **
|
||||
SELECT * FROM t1;
|
||||
@ -165,4 +163,3 @@ SET @@GLOBAL.query_cache_type = @old_cache_type;
|
||||
** Connection default **
|
||||
Disconnecting Connections con0, con1
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
|
@ -98,12 +98,13 @@ INSERT INTO t1(name) VALUES('Record_7');
|
||||
connection default;
|
||||
# wait until INSERT will be locked (low performance)
|
||||
let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE state= "Table lock" AND info LIKE "INSERT INTO t1%";
|
||||
WHERE state= "Waiting for table level lock" AND
|
||||
info LIKE "INSERT INTO t1%";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo ## show processlist info and state ##
|
||||
SELECT state,info FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE state= "Table lock" AND info LIKE "INSERT INTO t1%";
|
||||
WHERE state= "Waiting for table level lock" AND info LIKE "INSERT INTO t1%";
|
||||
--echo ## table contents befor UNLOCK ##
|
||||
SELECT * FROM t1;
|
||||
UNLOCK TABLES;
|
||||
|
@ -123,7 +123,7 @@ connection default;
|
||||
--echo ** Wait till con0 is blocked **
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = 'Table lock' AND info = '$my_select';
|
||||
WHERE state = 'Waiting for table level lock' AND info = '$my_select';
|
||||
--source include/wait_condition.inc
|
||||
UNLOCK TABLES;
|
||||
|
||||
@ -219,7 +219,7 @@ connection default;
|
||||
--echo ** Wait till con0 is blocked **
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = 'Table lock' AND info = '$my_select';
|
||||
WHERE state = 'Waiting for table level lock' AND info = '$my_select';
|
||||
--source include/wait_condition.inc
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
@ -60,8 +60,6 @@ INSERT INTO t1 VALUES(1, 'val1');
|
||||
INSERT INTO t1 VALUES(2, 'val2');
|
||||
INSERT INTO t1 VALUES(3, 'val3');
|
||||
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
|
||||
#
|
||||
# Clearing the query cache and setting up cache size
|
||||
#
|
||||
@ -101,7 +99,7 @@ SELECT * FROM t1;
|
||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
--echo 1 Expected
|
||||
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
|
||||
UNLOCK TABLES;
|
||||
|
||||
@ -129,7 +127,7 @@ SELECT * FROM t1;
|
||||
--echo ** Connection con0 **
|
||||
connection con0;
|
||||
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
|
||||
--echo ** Connection con1 **
|
||||
connection con1;
|
||||
@ -141,7 +139,8 @@ send SELECT * FROM t1;
|
||||
connection con0;
|
||||
|
||||
--echo wait until table is locked
|
||||
let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE state= 'Table lock';
|
||||
let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist
|
||||
WHERE state= 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
UNLOCK TABLES;
|
||||
|
||||
@ -177,7 +176,7 @@ SELECT * FROM t1;
|
||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||
--echo 1 Expected
|
||||
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
|
||||
UNLOCK TABLES;
|
||||
|
||||
@ -201,7 +200,7 @@ SELECT * FROM t1;
|
||||
|
||||
--echo ** Connection con0 **
|
||||
connection con0;
|
||||
LOCK TABLE v1 WRITE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
|
||||
--echo ** Connection con1 **
|
||||
connection con1;
|
||||
@ -283,7 +282,6 @@ disconnect con0;
|
||||
disconnect con1;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
|
||||
--enable_ps_protocol
|
||||
|
||||
|
@ -86,7 +86,9 @@ delimiter ;|
|
||||
--echo ** Connection con0 **
|
||||
connection con0;
|
||||
|
||||
let $wait_condition = SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state='Table lock' AND info LIKE 'UPDATE t1 SET a = CONCAT(a,"-updated")';
|
||||
let $wait_condition = SELECT COUNT(*) > 0 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table level lock' AND
|
||||
info LIKE 'UPDATE t1 SET a = CONCAT(a,"-updated")';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo ** Asynchronous Execution **
|
||||
@ -102,7 +104,8 @@ delimiter ;|
|
||||
--echo ** Connection default **
|
||||
connection default;
|
||||
|
||||
let $wait_condition= SELECT count(*) = 2 FROM information_schema.processlist WHERE state LIKE 'Table lock';
|
||||
let $wait_condition= SELECT count(*) = 2 FROM information_schema.processlist
|
||||
WHERE state LIKE 'Waiting for table level lock';
|
||||
--source include/wait_condition.inc
|
||||
UNLOCK TABLES;
|
||||
|
||||
@ -157,7 +160,9 @@ delimiter ;|
|
||||
--echo ** Connection con0 **
|
||||
connection con0;
|
||||
|
||||
let $wait_condition = SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state='Table lock' AND info LIKE 'UPDATE t1 SET a = CONCAT(a,"-updated")';
|
||||
let $wait_condition = SELECT COUNT(*) > 0 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table level lock' AND
|
||||
info LIKE 'UPDATE t1 SET a = CONCAT(a,"-updated")';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo ** Asynchronous Execution **
|
||||
@ -173,7 +178,8 @@ delimiter ;|
|
||||
--echo ** Connection default **
|
||||
connection default;
|
||||
|
||||
let $wait_condition= SELECT count(*) = 2 FROM information_schema.processlist WHERE state LIKE 'Table lock';
|
||||
let $wait_condition= SELECT count(*) = 2 FROM information_schema.processlist
|
||||
WHERE state LIKE 'Waiting for table level lock';
|
||||
--source include/wait_condition.inc
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
--source include/have_thread_concurrency.inc
|
||||
#
|
||||
# only global
|
||||
#
|
||||
|
@ -307,7 +307,7 @@ connection update;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where command = "Delayed insert" and state = "Table lock";
|
||||
where command = "Delayed insert" and state = "Waiting for table level lock";
|
||||
--source include/wait_condition.inc
|
||||
connect (select,localhost,root,,);
|
||||
--echo connection: select
|
||||
|
@ -19,3 +19,4 @@ plugin_load : Bug#55966 2010-08-13 alik "plugin" tests fail in 5.5
|
||||
plugin_not_embedded : Bug#55966 2010-08-13 alik "plugin" tests fail in 5.5
|
||||
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
|
||||
sp_sync : Bug#48157 2010-02-06 5.5-m3 demands a differnt solution
|
||||
ctype_utf8mb4_ndb : Bug#55799, Bug#51907, disabled by Konstantin 2010-08-06
|
||||
|
@ -121,3 +121,28 @@ let $wait_condition=
|
||||
|
||||
drop database events_test;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#54105 assert in MDL_context::release_locks_stored_before
|
||||
--echo #
|
||||
|
||||
USE test;
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP EVENT IF EXISTS e1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
CREATE TABLE t2 (a INT);
|
||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
||||
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SAVEPOINT A;
|
||||
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||
SHOW CREATE EVENT e1;
|
||||
SELECT * FROM t2;
|
||||
ROLLBACK WORK TO SAVEPOINT A;
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
@ -318,6 +318,58 @@ insert into t2 (a) values (3);
|
||||
--echo # --> connection default;
|
||||
connection default;
|
||||
unlock tables;
|
||||
--echo #
|
||||
--echo # Check that "FLUSH TABLES <list> WITH READ LOCK" is
|
||||
--echo # compatible with active "FLUSH TABLES WITH READ LOCK".
|
||||
--echo # Vice versa it is not true, since tables read-locked by
|
||||
--echo # "FLUSH TABLES <list> WITH READ LOCK" can't be flushed.
|
||||
flush tables with read lock;
|
||||
--echo # --> connection con1;
|
||||
connection con1;
|
||||
flush table t1 with read lock;
|
||||
select * from t1;
|
||||
unlock tables;
|
||||
--echo # --> connection default;
|
||||
connection default;
|
||||
unlock tables;
|
||||
--echo #
|
||||
--echo # Check that FLUSH TABLES t1 WITH READ LOCK
|
||||
--echo # does not conflict with an existing FLUSH TABLES t2
|
||||
--echo # WITH READ LOCK.
|
||||
--echo #
|
||||
flush table t1 with read lock;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
flush table t2 with read lock;
|
||||
unlock tables;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
unlock tables;
|
||||
--echo #
|
||||
--echo # Check that FLUSH TABLES t1 WITH READ LOCK
|
||||
--echo # does not conflict with SET GLOBAL read_only=1.
|
||||
--echo #
|
||||
set global read_only=1;
|
||||
--echo # connection con1
|
||||
connection con1;
|
||||
flush table t1 with read lock;
|
||||
unlock tables;
|
||||
--echo # connection default
|
||||
connection default;
|
||||
set global read_only=0;
|
||||
--echo #
|
||||
--echo # Check that it's possible to read-lock
|
||||
--echo # tables locked with FLUSH TABLE <list> WITH READ LOCK.
|
||||
--echo #
|
||||
flush tables t1, t2 with read lock;
|
||||
--echo # connection con1
|
||||
connection con1;
|
||||
lock table t1 read, t2 read;
|
||||
unlock tables;
|
||||
--echo # connection default
|
||||
connection default;
|
||||
unlock tables;
|
||||
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
disconnect con1;
|
||||
@ -355,3 +407,142 @@ drop temporary table v1;
|
||||
unlock tables;
|
||||
drop view v2, v3;
|
||||
drop table t1, v1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # FLUSH TABLES <list> WITH READ LOCK and HANDLER
|
||||
--echo #
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3);
|
||||
handler t1 open;
|
||||
handler t1 read a next;
|
||||
handler t1 read a next;
|
||||
flush tables t1 with read lock;
|
||||
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||
handler t1 read a next;
|
||||
unlock tables;
|
||||
--echo #
|
||||
--echo # Sic: lost handler position.
|
||||
--echo #
|
||||
handler t1 read a next;
|
||||
handler t1 close;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#52117 Pending FLUSH TALBES <list> aborts
|
||||
--echo # transactions unnecessarily.
|
||||
--echo #
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
--echo # --> conection default
|
||||
connection default;
|
||||
|
||||
create table t1 (a int);
|
||||
begin;
|
||||
select * from t1;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
--echo #
|
||||
--echo # Issue a LOCK TABLE t1 READ. We could use HANDLER t1 OPEN
|
||||
--echo # or a long-running select -- anything that
|
||||
--echo # prevents FLUSH TABLE t1 from immediate completion would do.
|
||||
--echo #
|
||||
lock table t1 read;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo #
|
||||
--echo # FLUSH TABLE expels the table definition from the cache.
|
||||
--echo # Sending 'flush table t1'...
|
||||
send flush table t1;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
--echo # Let flush table sync in.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table flush"
|
||||
and info = "flush table t1";
|
||||
--source include/wait_condition.inc
|
||||
send select * from t1;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table flush"
|
||||
and info = "select * from t1";
|
||||
select * from t1;
|
||||
unlock tables;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Reaping 'flush table t1'...
|
||||
reap;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
--echo # Reaping 'select * from t1'...
|
||||
reap;
|
||||
commit;
|
||||
|
||||
--echo #
|
||||
--echo # Repeat the same test but with FLUSH TABLES
|
||||
--echo #
|
||||
|
||||
begin;
|
||||
select * from t1;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
--echo #
|
||||
--echo # Issue a LOCK TABLE t1 READ.
|
||||
--echo #
|
||||
lock table t1 read;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo #
|
||||
--echo # FLUSH TABLES expels the table definition from the cache.
|
||||
--echo # Sending 'flush tables'...
|
||||
send flush tables;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
--echo # Let flush table sync in.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table flush"
|
||||
and info = "flush tables";
|
||||
--source include/wait_condition.inc
|
||||
send select * from t1;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table flush"
|
||||
and info = "select * from t1";
|
||||
select * from t1;
|
||||
unlock tables;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Reaping 'flush tables'...
|
||||
reap;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
--echo # Reaping 'select * from t1'...
|
||||
reap;
|
||||
commit;
|
||||
|
||||
--echo # Cleanup
|
||||
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
disconnect con1;
|
||||
--source include/wait_until_disconnected.inc
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
disconnect con2;
|
||||
--source include/wait_until_disconnected.inc
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
drop table t1;
|
||||
|
||||
|
@ -1470,7 +1470,8 @@ connection con3726_2;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info like "rename table t2 to t3";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info like "rename table t2 to t3";
|
||||
--source include/wait_condition.inc
|
||||
--echo # These statements should not be blocked by pending lock requests
|
||||
select table_name, column_name, data_type from information_schema.columns
|
||||
|
@ -89,3 +89,23 @@ from information_schema.referential_constraints
|
||||
where constraint_schema = schema();
|
||||
drop table t2;
|
||||
set foreign_key_checks = 1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#55973 Assertion `thd->transaction.stmt.is_empty()'
|
||||
--echo # on CREATE TABLE .. SELECT I_S.PART
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE VIEW v1 AS SELECT 1;
|
||||
# This used to case an assert.
|
||||
CREATE TABLE t1 engine = InnoDB AS
|
||||
SELECT * FROM information_schema.partitions
|
||||
WHERE table_schema= 'test' AND table_name= 'v1';
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
|
@ -42,7 +42,7 @@ let $wait_condition=
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE info = "DROP TABLE t1" and
|
||||
state = "Waiting for table";
|
||||
state = "Waiting for table metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
--echo # Connection 1 is now holding the lock.
|
||||
--echo # Issuing insert from connection 1 while connection 2&3
|
||||
@ -97,7 +97,8 @@ connection default;
|
||||
--echo # connection holds SW metadata lock on table to be altered.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 add column c4 int";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 add column c4 int";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # The below statement should succeed. It should not
|
||||
@ -196,7 +197,7 @@ connection default;
|
||||
--echo # Connection con1
|
||||
connection con1;
|
||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table' AND info='OPTIMIZE TABLE t1';
|
||||
WHERE state='Waiting for table metadata lock' AND info='OPTIMIZE TABLE t1';
|
||||
--source include/wait_condition.inc
|
||||
SELECT * FROM t1;
|
||||
COMMIT;
|
||||
@ -241,7 +242,7 @@ connection con2;
|
||||
--echo # Waiting for 'SELECT * FROM v1' to sync in.
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info = "SELECT * FROM v1";
|
||||
WHERE state = "Waiting for table metadata lock" AND info = "SELECT * FROM v1";
|
||||
--source include/wait_condition.inc
|
||||
# This should block due to v1 being locked.
|
||||
--echo # Sending:
|
||||
@ -252,7 +253,8 @@ connection con3;
|
||||
--echo # Waiting for 'ALTER VIEW v1 AS SELECT 2 FROM t2' to sync in.
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info = "ALTER VIEW v1 AS SELECT 2 FROM t2";
|
||||
WHERE state = "Waiting for table metadata lock" AND
|
||||
info = "ALTER VIEW v1 AS SELECT 2 FROM t2";
|
||||
--source include/wait_condition.inc
|
||||
# Unlock t1 allowing SELECT * FROM v1 to proceed.
|
||||
UNLOCK TABLES;
|
||||
|
@ -799,8 +799,9 @@ connection default;
|
||||
--echo # table as it acquires LOCK_S locks on rows of old version, which
|
||||
--echo # are compatible with locks acquired by connection 'con1'.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist where state =
|
||||
"Waiting for table" and info = "alter table t1 add column j int";
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 add column j int";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # The below statement will deadlock because it will try to acquire
|
||||
@ -844,7 +845,8 @@ connection default;
|
||||
--echo # Wait until ALTER is blocked because of active SR lock.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 rebuild partition p0";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 rebuild partition p0";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # The below statement should succeed as transaction
|
||||
|
@ -174,7 +174,7 @@ connection default;
|
||||
# we must wait till the insert opens and locks the table
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and id = $ID;
|
||||
where state = "Waiting for table level lock" and id = $ID;
|
||||
--source include/wait_condition.inc
|
||||
connect (select,localhost,root,,);
|
||||
--echo connection: select
|
||||
|
@ -357,7 +357,8 @@ let $ID= `select connection_id()`;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "rename table t1 to t2";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "rename table t1 to t2";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
eval kill query $ID;
|
||||
@ -372,7 +373,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "drop table t1";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -388,7 +389,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "create trigger t1_bi before insert on t1 for each row set @a:=1";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -407,7 +408,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 add column j int";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -423,7 +424,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 rename to t2";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -437,7 +438,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 disable keys";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -452,7 +453,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 alter column i set default 100";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -474,7 +475,7 @@ connection ddl;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t2 alter column i set default 100";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID ID
|
||||
@ -499,7 +500,7 @@ connection ddl;
|
||||
connection dml;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "rename tables t1 to t3, t2 to t1";
|
||||
--source include/wait_condition.inc
|
||||
let $ID2= `select connection_id()`;
|
||||
@ -508,7 +509,7 @@ let $ID2= `select connection_id()`;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "insert into t2 values (1)";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID2 ID2
|
||||
@ -536,7 +537,7 @@ connection ddl;
|
||||
connection dml;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables" and
|
||||
where state = "Waiting for table flush" and
|
||||
info = "flush tables";
|
||||
--source include/wait_condition.inc
|
||||
--send select * from t1
|
||||
@ -544,7 +545,7 @@ let $wait_condition=
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and
|
||||
where state = "Waiting for table flush" and
|
||||
info = "select * from t1";
|
||||
--source include/wait_condition.inc
|
||||
--replace_result $ID2 ID2
|
||||
|
@ -32,7 +32,8 @@ connection reader;
|
||||
# Sleep a bit till the update of connection writer is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "update low_priority t1 set n = 4";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "update low_priority t1 set n = 4";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
select n from t1;
|
||||
@ -40,7 +41,8 @@ connection locker2;
|
||||
# Sleep a bit till the select of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "select n from t1";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "select n from t1";
|
||||
--source include/wait_condition.inc
|
||||
select release_lock("mysqltest_lock");
|
||||
connection locker;
|
||||
@ -72,7 +74,8 @@ connection reader;
|
||||
# Sleep a bit till the update of connection writer is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "update low_priority t1 set n = 4";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "update low_priority t1 set n = 4";
|
||||
--source include/wait_condition.inc
|
||||
select n from t1;
|
||||
connection locker2;
|
||||
@ -120,7 +123,8 @@ insert t1 select * from t2;
|
||||
connection locker;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "insert t1 select * from t2";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "insert t1 select * from t2";
|
||||
--source include/wait_condition.inc
|
||||
drop table t2;
|
||||
unlock tables;
|
||||
@ -145,7 +149,8 @@ connection locker;
|
||||
# Sleep a bit till the insert of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "insert t1 select * from t2";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "insert t1 select * from t2";
|
||||
--source include/wait_condition.inc
|
||||
drop table t2;
|
||||
unlock tables;
|
||||
@ -191,7 +196,7 @@ connection locker;
|
||||
# Sleep a bit till the select of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info =
|
||||
WHERE state = "Waiting for table metadata lock" AND info =
|
||||
"SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1";
|
||||
--source include/wait_condition.inc
|
||||
# Make test case independent from earlier grants.
|
||||
@ -223,7 +228,8 @@ connection writer;
|
||||
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "FLUSH TABLES WITH READ LOCK";
|
||||
where state = "Waiting for global metadata lock" and
|
||||
info = "FLUSH TABLES WITH READ LOCK";
|
||||
--source include/wait_condition.inc
|
||||
# This must not block.
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
@ -254,7 +260,8 @@ connection writer;
|
||||
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "FLUSH TABLES WITH READ LOCK";
|
||||
where state = "Waiting for global metadata lock" and
|
||||
info = "FLUSH TABLES WITH READ LOCK";
|
||||
--source include/wait_condition.inc
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
CREATE TABLE t2 AS SELECT * FROM t1;
|
||||
@ -326,7 +333,8 @@ connection reader;
|
||||
# Wait till connection writer is blocked
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 auto_increment=0";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 auto_increment=0";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
alter table t1 auto_increment=0;
|
||||
@ -334,7 +342,8 @@ connection locker;
|
||||
# Wait till connection reader is blocked
|
||||
let $wait_condition=
|
||||
select count(*) = 2 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 auto_increment=0";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 auto_increment=0";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
connection writer;
|
||||
@ -367,7 +376,8 @@ connection con5;
|
||||
--echo # con5
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "flush tables with read lock";
|
||||
where state = "Waiting for global metadata lock" and
|
||||
info = "flush tables with read lock";
|
||||
--source include/wait_condition.inc
|
||||
--echo # global read lock is taken
|
||||
connection con3;
|
||||
@ -489,16 +499,20 @@ update t1 set i= 10;
|
||||
connection reader;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "update t1 set i= 10";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "update t1 set i= 10";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
select * from t1;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "select * from t1";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "select * from t1";
|
||||
--source include/wait_condition.inc
|
||||
let $ID= `select id from information_schema.processlist where state = "Table lock" and info = "update t1 set i= 10"`;
|
||||
let $ID= `select id from information_schema.processlist
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "update t1 set i= 10"`;
|
||||
--replace_result $ID ID
|
||||
eval kill query $ID;
|
||||
connection reader;
|
||||
@ -557,7 +571,7 @@ connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
alter table t1 add column j int;
|
||||
connect (insert,localhost,root,,test,,);
|
||||
@ -565,7 +579,7 @@ connection insert;
|
||||
--echo connection: insert
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
--send insert into t1 values (1,2);
|
||||
--echo connection: default
|
||||
@ -615,12 +629,12 @@ connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
flush tables;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
connection flush;
|
||||
@ -646,7 +660,8 @@ send insert into t1 values(1);
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and info = "insert into t1 values(1)";
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "insert into t1 values(1)";
|
||||
--source include/wait_condition.inc
|
||||
let $tlwb= `show status like 'Table_locks_waited'`;
|
||||
unlock tables;
|
||||
@ -683,12 +698,12 @@ connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
flush tables;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
drop table t1;
|
||||
connection flush;
|
||||
@ -725,7 +740,8 @@ connection default;
|
||||
--echo # connection holds SW metadata lock on table to be altered.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 add column c4 int";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 add column c4 int";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # The below statement should succeed. It should not
|
||||
@ -825,7 +841,8 @@ connection default;
|
||||
--echo # Wait until ALTER TABLE gets blocked.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 add column j int";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 add column j int";
|
||||
--source include/wait_condition.inc
|
||||
--echo # The below statement should try to acquire SW lock on 't1'
|
||||
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||
@ -855,7 +872,8 @@ connection default;
|
||||
--echo # Wait until ALTER TABLE gets blocked.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "alter table t1 drop column j";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "alter table t1 drop column j";
|
||||
--source include/wait_condition.inc
|
||||
--echo # The below statement should try to acquire SW lock on 't1'
|
||||
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||
@ -982,7 +1000,7 @@ connection con3;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Flushing tables" AND info = "FLUSH TABLES";
|
||||
WHERE state = "Waiting for table flush" AND info = "FLUSH TABLES";
|
||||
--source include/wait_condition.inc
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
SELECT * FROM t1;
|
||||
@ -1014,7 +1032,8 @@ connection con3;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info = "DROP TABLE t1, t2";
|
||||
WHERE state = "Waiting for table metadata lock" AND
|
||||
info = "DROP TABLE t1, t2";
|
||||
--source include/wait_condition.inc
|
||||
# Note: This query causes two timeouts.
|
||||
# 1: try_acquire_high_prio_shared_mdl_lock on t1
|
||||
@ -1069,7 +1088,8 @@ connection default;
|
||||
--echo # Wait until RENAME TABLE is blocked on table 't3'.
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info = "rename tables t1 to t2, t2 to t3";
|
||||
where state = "Waiting for table metadata lock" and
|
||||
info = "rename tables t1 to t2, t2 to t3";
|
||||
--source include/wait_condition.inc
|
||||
--echo # Kill RENAME TABLE.
|
||||
--replace_result $ID ID
|
||||
|
@ -898,7 +898,7 @@ set debug_sync= 'now WAIT_FOR parked';
|
||||
connection default;
|
||||
--echo # Wait until this LOCK TABLES statement starts waiting for table lock.
|
||||
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
||||
where state= 'Table lock' and
|
||||
where state= 'Waiting for table level lock' and
|
||||
info='lock table v1 write';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Allow SELECT ... FOR UPDATE to resume.
|
||||
@ -972,7 +972,7 @@ connection default;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = "Waiting for table"
|
||||
WHERE state = "Waiting for table metadata lock"
|
||||
AND info = "ALTER TABLE t1 ADD COLUMN j INT";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@ connection default;
|
||||
#--sleep 8
|
||||
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE ID = $con1_id AND STATE = 'Waiting for table';
|
||||
WHERE ID = $con1_id AND STATE = 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
#SELECT NOW();
|
||||
--echo # Kick INSERT out of thr_multi_lock().
|
||||
@ -61,7 +61,7 @@ FLUSH TABLES;
|
||||
#--sleep 8
|
||||
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE ID = $con1_id AND STATE = 'Waiting for table';
|
||||
WHERE ID = $con1_id AND STATE = 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
#SELECT NOW();
|
||||
--echo # Unlock and close table and wait for con1 to close too.
|
||||
|
@ -497,7 +497,7 @@ connection updater;
|
||||
# Wait till "alter table t1 ..." of session changer is in work.
|
||||
# = There is one session waiting.
|
||||
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
||||
where state= 'Waiting for table';
|
||||
where state= 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
send update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
|
||||
|
||||
@ -508,7 +508,7 @@ connection locker;
|
||||
# are in work.
|
||||
# = There are two session waiting.
|
||||
let $wait_condition= select count(*)= 2 from information_schema.processlist
|
||||
where state= 'Waiting for table';
|
||||
where state= 'Waiting for table metadata lock';
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
|
||||
|
@ -498,12 +498,20 @@ drop table t1,t2,t3,t4;
|
||||
set query_cache_wlock_invalidate=1;
|
||||
create table t1 (a int not null);
|
||||
create table t2 (a int not null);
|
||||
create view v1 as select * from t1;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
lock table t1 write, t2 read;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
unlock table;
|
||||
select * from t1;
|
||||
# Implicit locking of t1 does not invalidate QC
|
||||
show status like "Qcache_queries_in_cache";
|
||||
lock table v1 write;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
unlock table;
|
||||
drop view v1;
|
||||
drop table t1,t2;
|
||||
set query_cache_wlock_invalidate=default;
|
||||
|
||||
|
@ -58,18 +58,18 @@ connection user3;
|
||||
# Typical information_schema.processlist content after sufficient sleep time
|
||||
# ID USER COMMAND TIME STATE INFO
|
||||
# ....
|
||||
# 2 root Query 5 Table lock SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
|
||||
# 2 root Query 5 Waiting for table level lock SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
|
||||
# ....
|
||||
# XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
# The values marked with 'X' must be reached.
|
||||
--echo # Poll till the select of connection user1 is blocked by the write lock on t1.
|
||||
let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE state = 'Table lock'
|
||||
WHERE state = 'Waiting for table level lock'
|
||||
AND info = '$select_for_qc';
|
||||
--source include/wait_condition.inc
|
||||
eval
|
||||
SELECT user,command,state,info FROM information_schema.processlist
|
||||
WHERE state = 'Table lock'
|
||||
WHERE state = 'Waiting for table level lock'
|
||||
AND info = '$select_for_qc';
|
||||
INSERT INTO t1 VALUES (4);
|
||||
|
||||
|
@ -23,7 +23,6 @@ drop schema foo;
|
||||
|
||||
--disable_warnings
|
||||
DROP SCHEMA IF EXISTS schema1;
|
||||
DROP SCHEMA IF EXISTS schema2;
|
||||
--enable_warnings
|
||||
|
||||
connect(con2, localhost, root);
|
||||
@ -32,7 +31,6 @@ connect(con2, localhost, root);
|
||||
connection default;
|
||||
|
||||
CREATE SCHEMA schema1;
|
||||
CREATE SCHEMA schema2;
|
||||
CREATE TABLE schema1.t1 (a INT);
|
||||
|
||||
SET autocommit= FALSE;
|
||||
@ -45,10 +43,13 @@ connection con2;
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
||||
WHERE state= 'Waiting for table'
|
||||
WHERE state= 'Waiting for table metadata lock'
|
||||
AND info='DROP SCHEMA schema1';
|
||||
--source include/wait_condition.inc
|
||||
ALTER SCHEMA schema2 DEFAULT CHARACTER SET utf8;
|
||||
# Error 1 is from ALTER DATABASE when the database does not exist.
|
||||
# Listing the error twice to prevent result diffences based on filename.
|
||||
--error 1,1
|
||||
ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8;
|
||||
SET autocommit= TRUE;
|
||||
|
||||
--echo # Connection 2
|
||||
@ -57,7 +58,6 @@ connection con2;
|
||||
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
DROP SCHEMA schema2;
|
||||
disconnect con2;
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ connection con2;
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table' and info='DROP SCHEMA schema1';
|
||||
WHERE state='Waiting for schema metadata lock' and info='DROP SCHEMA schema1';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # CREATE SCHEMA used to give a deadlock.
|
||||
@ -124,7 +124,7 @@ connection default;
|
||||
--echo # Connection con2
|
||||
connect (con2, localhost, root);
|
||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table' AND info='DROP DATABASE db1';
|
||||
WHERE state='Waiting for table metadata lock' AND info='DROP DATABASE db1';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo # Connection con1
|
||||
@ -172,7 +172,7 @@ connection con2;
|
||||
--echo # Connection 3
|
||||
connection con3;
|
||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
||||
WHERE state='Waiting for table' and info='DROP DATABASE db1';
|
||||
WHERE state='Waiting for table metadata lock' and info='DROP DATABASE db1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # But it should still be possible to CREATE/ALTER/DROP other databases.
|
||||
CREATE DATABASE db2;
|
||||
|
@ -183,18 +183,19 @@ connection con1;
|
||||
send drop procedure p1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop procedure t1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop procedure t1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop procedure p1';
|
||||
where state='Waiting for stored procedure metadata lock' and
|
||||
info='drop procedure p1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored procedure metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -222,18 +223,19 @@ connection con1;
|
||||
send create procedure p1() begin end;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'create procedure t1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'create procedure t1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='create procedure p1() begin end';
|
||||
where state='Waiting for stored procedure metadata lock' and
|
||||
info='create procedure p1() begin end';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored procedure metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -259,18 +261,19 @@ connection con1;
|
||||
send alter procedure p1 contains sql;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'alter procedure t1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'alter procedure t1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='alter procedure p1 contains sql';
|
||||
where state='Waiting for stored procedure metadata lock' and
|
||||
info='alter procedure p1 contains sql';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored procedure metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -296,18 +299,19 @@ connection con1;
|
||||
send drop function f1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f1';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored function metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -335,18 +339,19 @@ connection con1;
|
||||
send create function f1() returns int return 2;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'create function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'create function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='create function f1() returns int return 2';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='create function f1() returns int return 2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored function metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -373,18 +378,19 @@ connection con1;
|
||||
send alter function f1 contains sql;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'alter function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'alter function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='alter function f1 contains sql';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='alter function f1 contains sql';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Demonstrate that there is a pending exclusive lock.
|
||||
--echo # Sending 'select f1()'...
|
||||
send select f1();
|
||||
--echo # --> connection con3
|
||||
connection con3;
|
||||
--echo # Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
--echo # Waiting for 'select f1()' to get blocked by a pending MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1()';
|
||||
where state='Waiting for stored function metadata lock' and info='select f1()';
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
commit;
|
||||
@ -471,9 +477,10 @@ connection con1;
|
||||
send drop function f1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f1';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connnection default
|
||||
connection default;
|
||||
@ -497,9 +504,10 @@ connection con1;
|
||||
send drop function f1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f1';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connnection default
|
||||
connection default;
|
||||
@ -530,9 +538,10 @@ connection con1;
|
||||
send drop procedure p1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop procedure p1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop procedure p1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop procedure p1';
|
||||
where state='Waiting for stored procedure metadata lock' and
|
||||
info='drop procedure p1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connnection default
|
||||
connection default;
|
||||
@ -561,9 +570,10 @@ connection con1;
|
||||
send drop function f2;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f2' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f2';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f2';
|
||||
--source include/wait_condition.inc
|
||||
--echo # --> connnection default
|
||||
connection default;
|
||||
@ -623,17 +633,19 @@ connection con1;
|
||||
send drop function f1;
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f1' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f1';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f1';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Sending 'drop function f2'...
|
||||
send drop function f2;
|
||||
--echo # --> connection default
|
||||
connection default;
|
||||
--echo # Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'drop function f2' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='drop function f2';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='drop function f2';
|
||||
--source include/wait_condition.inc
|
||||
rollback to savepoint sv;
|
||||
--echo # --> connection con2
|
||||
@ -699,16 +711,18 @@ connection con1;
|
||||
send alter function f1 comment "comment";
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info like 'alter function f1 comment%';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info like 'alter function f1 comment%';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Sending 'call p1()'...
|
||||
send call p1();
|
||||
connection default;
|
||||
--echo # Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
--echo # Waiting for 'call p1()' to get blocked on MDL lock on f1...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1() into @var';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='select f1() into @var';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
@ -746,9 +760,10 @@ connection con1;
|
||||
send alter function f1 comment "comment";
|
||||
--echo # --> connection con2
|
||||
connection con2;
|
||||
--echo # Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
--echo # Waiting for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info like 'alter function f1 comment%';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info like 'alter function f1 comment%';
|
||||
--source include/wait_condition.inc
|
||||
delimiter |;
|
||||
--echo #
|
||||
@ -774,9 +789,10 @@ delimiter ;|
|
||||
--echo # Sending 'call p1()'...
|
||||
send call p1();
|
||||
connection default;
|
||||
--echo # Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
--echo # Waiting for 'call p1()' to get blocked on MDL lock on f1...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='Waiting for table' and info='select f1() into @var';
|
||||
where state='Waiting for stored function metadata lock' and
|
||||
info='select f1() into @var';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
@ -825,7 +841,7 @@ connection default;
|
||||
send select f3();
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
--echo # Waitng for 'select f3()' to get blocked on the user level lock...
|
||||
--echo # Waiting for 'select f3()' to get blocked on the user level lock...
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='User lock' and info='select f1() into @var';
|
||||
--source include/wait_condition.inc
|
||||
|
@ -322,7 +322,7 @@ set session low_priority_updates=on;
|
||||
connection rl_wait;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Table lock" and
|
||||
where state = "Waiting for table level lock" and
|
||||
info = "update t1 set value='updated' where value='old'";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
|
@ -87,7 +87,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR locked';
|
||||
--echo # Connection con3
|
||||
connection con3;
|
||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
||||
WHERE state= 'Waiting for table'
|
||||
WHERE state= 'Waiting for stored function metadata lock'
|
||||
AND info='SHOW OPEN TABLES WHERE f1()=0';
|
||||
--source include/wait_condition.inc
|
||||
--echo # Check that the IS query is blocked before releasing the x-lock
|
||||
|
@ -58,7 +58,8 @@ let $ID= `select connection_id()`;
|
||||
connection con2;
|
||||
--echo # Switched to connection: con2
|
||||
# wait for the other query to start executing
|
||||
let $wait_condition= select 1 from INFORMATION_SCHEMA.PROCESSLIST where ID = $ID and STATE = "Table lock";
|
||||
let $wait_condition= select 1 from INFORMATION_SCHEMA.PROCESSLIST
|
||||
where ID = $ID and STATE = "Waiting for table level lock";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
|
||||
|
@ -896,7 +896,7 @@ connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table";
|
||||
where state = "Waiting for global metadata lock";
|
||||
--source include/wait_condition.inc
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
unlock tables;
|
||||
|
@ -4074,7 +4074,8 @@ connection default;
|
||||
connection con2;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 from information_schema.processlist
|
||||
WHERE state = "Table lock" AND info = "INSERT INTO t1 SELECT * FROM v1";
|
||||
WHERE state = "Waiting for table level lock" AND
|
||||
info = "INSERT INTO t1 SELECT * FROM v1";
|
||||
--source include/wait_condition.inc
|
||||
--echo # ... then try to drop the view. This should block.
|
||||
--echo # Sending:
|
||||
@ -4084,7 +4085,7 @@ let $wait_condition=
|
||||
connection con3;
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 from information_schema.processlist
|
||||
WHERE state = "Waiting for table" AND info = "DROP VIEW v1";
|
||||
WHERE state = "Waiting for table metadata lock" AND info = "DROP VIEW v1";
|
||||
--source include/wait_condition.inc
|
||||
--echo # Now allow CALL p1() to complete
|
||||
UNLOCK TABLES;
|
||||
|
@ -428,7 +428,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
|
||||
thread_var->current_cond= cond;
|
||||
data->cond= cond;
|
||||
|
||||
old_proc_info= proc_info_hook(NULL, "Table lock",
|
||||
old_proc_info= proc_info_hook(NULL, "Waiting for table level lock",
|
||||
__func__, __FILE__, __LINE__);
|
||||
|
||||
set_timespec(wait_timeout, lock_wait_timeout);
|
||||
|
@ -71,6 +71,9 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
|
||||
|
||||
rwp->state = 0;
|
||||
rwp->waiters = 0;
|
||||
#ifdef SAFE_MUTEX
|
||||
rwp->write_thread = 0;
|
||||
#endif
|
||||
/* If attribute argument is NULL use default value - prefer writers. */
|
||||
rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
|
||||
|
||||
@ -80,6 +83,7 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
|
||||
|
||||
int my_rw_destroy(my_rw_lock_t *rwp)
|
||||
{
|
||||
DBUG_ASSERT(rwp->state == 0);
|
||||
pthread_mutex_destroy( &rwp->lock );
|
||||
pthread_cond_destroy( &rwp->readers );
|
||||
pthread_cond_destroy( &rwp->writers );
|
||||
@ -123,10 +127,15 @@ int my_rw_wrlock(my_rw_lock_t *rwp)
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
rwp->waiters++; /* another writer queued */
|
||||
|
||||
my_rw_lock_assert_not_write_owner(rwp);
|
||||
|
||||
while (rwp->state)
|
||||
pthread_cond_wait(&rwp->writers, &rwp->lock);
|
||||
rwp->state = -1;
|
||||
rwp->waiters--;
|
||||
#ifdef SAFE_MUTEX
|
||||
rwp->write_thread= pthread_self();
|
||||
#endif
|
||||
pthread_mutex_unlock(&rwp->lock);
|
||||
return(0);
|
||||
}
|
||||
@ -142,6 +151,9 @@ int my_rw_trywrlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
res=0;
|
||||
rwp->state = -1;
|
||||
#ifdef SAFE_MUTEX
|
||||
rwp->write_thread= pthread_self();
|
||||
#endif
|
||||
}
|
||||
pthread_mutex_unlock(&rwp->lock);
|
||||
return(res);
|
||||
@ -154,9 +166,15 @@ int my_rw_unlock(my_rw_lock_t *rwp)
|
||||
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
|
||||
DBUG_ASSERT(rwp->state != 0);
|
||||
|
||||
if (rwp->state == -1) /* writer releasing */
|
||||
{
|
||||
my_rw_lock_assert_write_owner(rwp);
|
||||
rwp->state= 0; /* mark as available */
|
||||
#ifdef SAFE_MUTEX
|
||||
rwp->write_thread= 0;
|
||||
#endif
|
||||
|
||||
if ( rwp->waiters ) /* writers queued */
|
||||
pthread_cond_signal( &rwp->writers );
|
||||
|
@ -74,6 +74,7 @@ SET (SQL_SOURCE
|
||||
sql_profile.cc event_parse_data.cc sql_alter.cc
|
||||
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
|
||||
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
|
||||
sql_reload.cc
|
||||
${GEN_SOURCES}
|
||||
${MYSYS_LIBWRAP_SOURCE})
|
||||
|
||||
|
@ -40,6 +40,7 @@ DTRACEFILES = filesort.o \
|
||||
sql_cursor.o \
|
||||
sql_delete.o \
|
||||
sql_truncate.o \
|
||||
sql_reload.o \
|
||||
sql_insert.o \
|
||||
datadict.o \
|
||||
sql_parse.o \
|
||||
@ -59,6 +60,7 @@ DTRACEFILES_DEPEND = filesort.o \
|
||||
sql_cursor.o \
|
||||
sql_delete.o \
|
||||
sql_truncate.o \
|
||||
sql_reload.o \
|
||||
sql_insert.o \
|
||||
datadict.o \
|
||||
sql_parse.o \
|
||||
@ -126,7 +128,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
||||
contributors.h sql_servers.h sql_signal.h records.h \
|
||||
sql_prepare.h rpl_handler.h replication.h mdl.h \
|
||||
sql_plist.h transaction.h sys_vars.h sql_truncate.h \
|
||||
sql_admin.h datadict.h
|
||||
sql_admin.h sql_reload.h datadict.h
|
||||
|
||||
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
item.cc item_sum.cc item_buff.cc item_func.cc \
|
||||
@ -140,7 +142,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
sql_connect.cc scheduler.cc sql_parse.cc \
|
||||
keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \
|
||||
sql_base.cc table.cc sql_select.cc sql_insert.cc \
|
||||
datadict.cc sql_profile.cc \
|
||||
sql_reload.cc datadict.cc sql_profile.cc \
|
||||
sql_prepare.cc sql_error.cc sql_locale.cc \
|
||||
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
|
||||
procedure.cc sql_test.cc sql_admin.cc \
|
||||
|
@ -177,9 +177,7 @@ bool dd_recreate_table(THD *thd, const char *db, const char *table_name)
|
||||
build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
|
||||
|
||||
/* Attempt to reconstruct the table. */
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
error= ha_create_table(thd, path, db, table_name, &create_info, TRUE);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@ -996,24 +996,33 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
|
||||
LEX_STRING name, Event_basic *etn)
|
||||
{
|
||||
bool ret;
|
||||
TABLE *table= NULL;
|
||||
ulong saved_mode= thd->variables.sql_mode;
|
||||
Open_tables_backup open_tables_backup;
|
||||
TABLE_LIST event_table;
|
||||
|
||||
DBUG_ENTER("Event_db_repository::load_named_event");
|
||||
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd,
|
||||
(int) name.length, name.str));
|
||||
|
||||
event_table.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
|
||||
|
||||
/* Reset sql_mode during data dictionary operations. */
|
||||
thd->variables.sql_mode= 0;
|
||||
|
||||
if (!(ret= open_event_table(thd, TL_READ, &table)))
|
||||
/*
|
||||
We don't use open_event_table() here to make sure that SHOW
|
||||
CREATE EVENT works properly in transactional context, and
|
||||
does not release transactional metadata locks when the
|
||||
event table is closed.
|
||||
*/
|
||||
if (!(ret= open_system_tables_for_read(thd, &event_table, &open_tables_backup)))
|
||||
{
|
||||
if ((ret= find_named_event(dbname, name, table)))
|
||||
if ((ret= find_named_event(dbname, name, event_table.table)))
|
||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||
else if ((ret= etn->load_from_row(thd, table)))
|
||||
else if ((ret= etn->load_from_row(thd, event_table.table)))
|
||||
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
|
||||
|
||||
close_mysql_tables(thd);
|
||||
close_system_tables(thd, &open_tables_backup);
|
||||
}
|
||||
|
||||
thd->variables.sql_mode= saved_mode;
|
||||
|
@ -699,7 +699,6 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
|
||||
bool
|
||||
Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
||||
{
|
||||
Open_tables_backup open_tables_backup;
|
||||
Event_timed et;
|
||||
bool ret;
|
||||
|
||||
@ -722,9 +721,7 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
||||
deadlock can occur please refer to the description of 'system table'
|
||||
flag.
|
||||
*/
|
||||
thd->reset_n_backup_open_tables_state(&open_tables_backup);
|
||||
ret= db_repository->load_named_event(thd, dbname, name, &et);
|
||||
thd->restore_backup_open_tables_state(&open_tables_backup);
|
||||
|
||||
if (!ret)
|
||||
ret= send_show_create_event(thd, &et, thd->protocol);
|
||||
|
@ -680,7 +680,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= m_dbname;
|
||||
table_list.alias= table_list.table_name= m_tabname;
|
||||
close_cached_tables(thd, &table_list, FALSE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -5702,7 +5702,7 @@ int ha_ndbcluster::create(const char *name,
|
||||
m_table->getObjectVersion(),
|
||||
(is_truncate) ?
|
||||
SOT_TRUNCATE_TABLE : SOT_CREATE_TABLE,
|
||||
0, 0, 1);
|
||||
0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -6143,7 +6143,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
||||
old_dbname, m_tabname,
|
||||
ndb_table_id, ndb_table_version,
|
||||
SOT_RENAME_TABLE,
|
||||
m_dbname, new_tabname, 1);
|
||||
m_dbname, new_tabname);
|
||||
}
|
||||
|
||||
// If we are moving tables between databases, we need to recreate
|
||||
@ -6337,7 +6337,7 @@ retry_temporary_error1:
|
||||
thd->query(), thd->query_length(),
|
||||
share->db, share->table_name,
|
||||
ndb_table_id, ndb_table_version,
|
||||
SOT_DROP_TABLE, 0, 0, 1);
|
||||
SOT_DROP_TABLE, 0, 0);
|
||||
}
|
||||
else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op
|
||||
will do a force GCP */
|
||||
@ -7019,7 +7019,6 @@ int ndbcluster_drop_database_impl(const char *path)
|
||||
while ((tabname=it++))
|
||||
{
|
||||
tablename_to_filename(tabname, tmp, FN_REFLEN - (tmp - full_path)-1);
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (ha_ndbcluster::delete_table(0, ndb, full_path, dbname, tabname))
|
||||
{
|
||||
const NdbError err= dict->getNdbError();
|
||||
@ -7029,7 +7028,6 @@ int ndbcluster_drop_database_impl(const char *path)
|
||||
ret= ndb_to_mysql_error(&err);
|
||||
}
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
@ -7056,7 +7054,7 @@ static void ndbcluster_drop_database(handlerton *hton, char *path)
|
||||
ha_ndbcluster::set_dbname(path, db);
|
||||
ndbcluster_log_schema_op(thd, 0,
|
||||
thd->query(), thd->query_length(),
|
||||
db, "", 0, 0, SOT_DROP_DB, 0, 0, 0);
|
||||
db, "", 0, 0, SOT_DROP_DB, 0, 0);
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -7181,7 +7179,6 @@ int ndbcluster_find_all_files(THD *thd)
|
||||
my_free(data);
|
||||
my_free(pack_data);
|
||||
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (discover)
|
||||
{
|
||||
/* ToDo 4.1 database needs to be created if missing */
|
||||
@ -7199,7 +7196,6 @@ int ndbcluster_find_all_files(THD *thd)
|
||||
TRUE);
|
||||
}
|
||||
#endif
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
}
|
||||
while (unhandled && retries);
|
||||
@ -7292,19 +7288,16 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
file_name->str, reg_ext, 0);
|
||||
if (my_access(name, F_OK))
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
DBUG_PRINT("info", ("Table %s listed and need discovery",
|
||||
file_name->str));
|
||||
if (ndb_create_table_from_engine(thd, db, file_name->str))
|
||||
{
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_TABLE_EXISTS_ERROR,
|
||||
"Discover of table %s.%s failed",
|
||||
db, file_name->str);
|
||||
continue;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name->str));
|
||||
file_on_disk= TRUE;
|
||||
@ -7361,10 +7354,8 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
file_name_str= (char*)my_hash_element(&ok_tables, i);
|
||||
end= end1 +
|
||||
tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name));
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
ndbcluster_create_binlog_setup(ndb, name, end-name,
|
||||
db, file_name_str, TRUE);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -7426,7 +7417,6 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
}
|
||||
|
||||
/* Lock mutex before creating .FRM files. */
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
/* Create new files. */
|
||||
List_iterator_fast<char> it2(create_list);
|
||||
while ((file_name_str=it2++))
|
||||
@ -7441,8 +7431,6 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
}
|
||||
}
|
||||
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
my_hash_free(&ok_tables);
|
||||
my_hash_free(&ndb_tables);
|
||||
|
||||
@ -8452,8 +8440,7 @@ int handle_trailing_share(NDB_SHARE *share)
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= share->db;
|
||||
table_list.alias= table_list.table_name= share->table_name;
|
||||
mysql_mutex_assert_owner(&LOCK_open);
|
||||
close_cached_tables(thd, &table_list, TRUE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
|
||||
mysql_mutex_lock(&ndbcluster_mutex);
|
||||
/* ndb_share reference temporary free */
|
||||
@ -10612,13 +10599,13 @@ int ndbcluster_alter_tablespace(handlerton *hton,
|
||||
thd->query(), thd->query_length(),
|
||||
"", alter_info->tablespace_name,
|
||||
0, 0,
|
||||
SOT_TABLESPACE, 0, 0, 0);
|
||||
SOT_TABLESPACE, 0, 0);
|
||||
else
|
||||
ndbcluster_log_schema_op(thd, 0,
|
||||
thd->query(), thd->query_length(),
|
||||
"", alter_info->logfile_group_name,
|
||||
0, 0,
|
||||
SOT_LOGFILE_GROUP, 0, 0, 0);
|
||||
SOT_LOGFILE_GROUP, 0, 0);
|
||||
#endif
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
|
@ -360,7 +360,6 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share,
|
||||
int error;
|
||||
DBUG_ENTER("ndbcluster_binlog_open_table");
|
||||
|
||||
mysql_mutex_assert_owner(&LOCK_open);
|
||||
init_tmp_table_share(thd, table_share, share->db, 0, share->table_name,
|
||||
share->key);
|
||||
if ((error= open_table_def(thd, table_share, 0)))
|
||||
@ -376,7 +375,9 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share,
|
||||
free_table_share(table_share);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
assign_new_table_id(table_share);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
if (!reopen)
|
||||
{
|
||||
@ -625,7 +626,7 @@ ndbcluster_binlog_log_query(handlerton *hton, THD *thd, enum_binlog_command binl
|
||||
{
|
||||
ndbcluster_log_schema_op(thd, 0, query, query_length,
|
||||
db, table_name, 0, 0, type,
|
||||
0, 0, 0);
|
||||
0, 0);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -908,9 +909,7 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
|
||||
if (!ndb_schema_share &&
|
||||
ndbcluster_check_ndb_schema_share() == 0)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_SCHEMA_TABLE);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
if (!ndb_schema_share)
|
||||
{
|
||||
ndbcluster_create_schema_table(thd);
|
||||
@ -922,9 +921,7 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
|
||||
if (!ndb_apply_status_share &&
|
||||
ndbcluster_check_ndb_apply_status_share() == 0)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_APPLY_TABLE);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
if (!ndb_apply_status_share)
|
||||
{
|
||||
ndbcluster_create_ndb_apply_status_table(thd);
|
||||
@ -934,12 +931,10 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
|
||||
}
|
||||
if (!ndbcluster_find_all_files(thd))
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
ndb_binlog_tables_inited= TRUE;
|
||||
if (opt_ndb_extra_logging)
|
||||
sql_print_information("NDB Binlog: ndb tables writable");
|
||||
close_cached_tables(NULL, NULL, TRUE, FALSE);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT);
|
||||
/* Signal injector thread that all is setup */
|
||||
mysql_cond_signal(&injector_cond);
|
||||
}
|
||||
@ -1276,8 +1271,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
|
||||
uint32 ndb_table_id,
|
||||
uint32 ndb_table_version,
|
||||
enum SCHEMA_OP_TYPE type,
|
||||
const char *new_db, const char *new_table_name,
|
||||
int have_lock_open)
|
||||
const char *new_db, const char *new_table_name)
|
||||
{
|
||||
DBUG_ENTER("ndbcluster_log_schema_op");
|
||||
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
||||
@ -1580,11 +1574,6 @@ end:
|
||||
|
||||
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
||||
mysql_mutex_lock(&ndb_schema_object->mutex);
|
||||
if (have_lock_open)
|
||||
{
|
||||
mysql_mutex_assert_owner(&LOCK_open);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
struct timespec abstime;
|
||||
@ -1640,10 +1629,6 @@ end:
|
||||
"distributing", ndb_schema_object->key);
|
||||
}
|
||||
}
|
||||
if (have_lock_open)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
}
|
||||
mysql_mutex_unlock(&ndb_schema_object->mutex);
|
||||
}
|
||||
|
||||
@ -1726,7 +1711,6 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
||||
{
|
||||
DBUG_DUMP("frm", (uchar*) altered_table->getFrmData(),
|
||||
altered_table->getFrmLength());
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
Ndb_table_guard ndbtab_g(dict, tabname);
|
||||
const NDBTAB *old= ndbtab_g.get_table();
|
||||
if (!old &&
|
||||
@ -1752,7 +1736,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= (char *)dbname;
|
||||
table_list.alias= table_list.table_name= (char *)tabname;
|
||||
close_cached_tables(thd, &table_list, TRUE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
|
||||
if ((error= ndbcluster_binlog_open_table(thd, share,
|
||||
table_share, table, 1)))
|
||||
@ -1763,8 +1747,6 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
||||
table_share= share->table_share;
|
||||
dbname= table_share->db.str;
|
||||
tabname= table_share->table_name.str;
|
||||
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
my_free(data);
|
||||
my_free(pack_data);
|
||||
@ -1858,7 +1840,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= (char *)dbname;
|
||||
table_list.alias= table_list.table_name= (char *)tabname;
|
||||
close_cached_tables(thd, &table_list, FALSE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
/* ndb_share reference create free */
|
||||
DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u",
|
||||
share->key, share->use_count));
|
||||
@ -1979,7 +1961,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= schema->db;
|
||||
table_list.alias= table_list.table_name= schema->name;
|
||||
close_cached_tables(thd, &table_list, FALSE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
}
|
||||
/* ndb_share reference temporary free */
|
||||
if (share)
|
||||
@ -1991,7 +1973,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
|
||||
}
|
||||
// fall through
|
||||
case SOT_CREATE_TABLE:
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
||||
{
|
||||
DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'",
|
||||
@ -2005,7 +1986,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
|
||||
{
|
||||
print_could_not_discover_error(thd, schema);
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
log_query= 1;
|
||||
break;
|
||||
case SOT_DROP_DB:
|
||||
@ -2096,7 +2076,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
|
||||
mysql_mutex_unlock(&ndb_schema_share_mutex);
|
||||
/* end protect ndb_schema_share */
|
||||
|
||||
close_cached_tables(NULL, NULL, FALSE, FALSE);
|
||||
close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT);
|
||||
// fall through
|
||||
case NDBEVENT::TE_ALTER:
|
||||
ndb_handle_schema_change(thd, ndb, pOp, tmp_share);
|
||||
@ -2253,7 +2233,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= schema->db;
|
||||
table_list.alias= table_list.table_name= schema->name;
|
||||
close_cached_tables(thd, &table_list, FALSE, FALSE);
|
||||
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||
}
|
||||
if (schema_type != SOT_ALTER_TABLE)
|
||||
break;
|
||||
@ -2274,7 +2254,6 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
|
||||
free_share(&share);
|
||||
share= 0;
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
||||
{
|
||||
DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'",
|
||||
@ -2288,7 +2267,6 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
|
||||
{
|
||||
print_could_not_discover_error(thd, schema);
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -3154,8 +3132,6 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
||||
#ifdef SYNC_DROP_
|
||||
thd->proc_info= "Syncing ndb table schema operation and binlog";
|
||||
mysql_mutex_lock(&share->mutex);
|
||||
mysql_mutex_assert_owner(&LOCK_open);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
||||
while (share->op)
|
||||
{
|
||||
@ -3181,7 +3157,6 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
||||
type_str, share->key);
|
||||
}
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
mysql_mutex_unlock(&share->mutex);
|
||||
#else
|
||||
mysql_mutex_lock(&share->mutex);
|
||||
@ -3963,9 +3938,9 @@ restart:
|
||||
!ndb_binlog_running))
|
||||
break; /* Shutting down server */
|
||||
|
||||
if (ndb_binlog_index && ndb_binlog_index->s->needs_reopen())
|
||||
if (ndb_binlog_index && ndb_binlog_index->s->has_old_version())
|
||||
{
|
||||
if (ndb_binlog_index->s->needs_reopen())
|
||||
if (ndb_binlog_index->s->has_old_version())
|
||||
{
|
||||
trans_commit_stmt(thd);
|
||||
close_thread_tables(thd);
|
||||
|
@ -158,8 +158,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
|
||||
uint32 ndb_table_version,
|
||||
enum SCHEMA_OP_TYPE type,
|
||||
const char *new_db,
|
||||
const char *new_table_name,
|
||||
int have_lock_open);
|
||||
const char *new_table_name);
|
||||
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
||||
NDB_SHARE *share,
|
||||
const char *type_str);
|
||||
|
@ -3670,6 +3670,34 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
|
||||
DBUG_RETURN(error != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Try to find a table in a storage engine.
|
||||
|
||||
@param db Normalized table schema name
|
||||
@param name Normalized table name.
|
||||
@param[out] exists Only valid if the function succeeded.
|
||||
|
||||
@retval TRUE An error is found
|
||||
@retval FALSE Success, check *exists
|
||||
*/
|
||||
|
||||
bool
|
||||
ha_check_if_table_exists(THD* thd, const char *db, const char *name,
|
||||
bool *exists)
|
||||
{
|
||||
uchar *frmblob= NULL;
|
||||
size_t frmlen;
|
||||
DBUG_ENTER("ha_check_if_table_exists");
|
||||
|
||||
*exists= ! ha_discover(thd, db, name, &frmblob, &frmlen);
|
||||
if (*exists)
|
||||
my_free(frmblob);
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
void st_ha_check_opt::init()
|
||||
{
|
||||
flags= sql_flags= 0;
|
||||
|
@ -2119,6 +2119,8 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
|
||||
|
||||
/* discovery */
|
||||
int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
|
||||
bool ha_check_if_table_exists(THD* thd, const char *db, const char *name,
|
||||
bool *exists);
|
||||
int ha_discover(THD* thd, const char* dbname, const char* name,
|
||||
uchar** frmblob, size_t* frmlen);
|
||||
int ha_find_files(THD *thd,const char *db,const char *path,
|
||||
|
24
sql/lock.cc
24
sql/lock.cc
@ -1298,27 +1298,19 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
|
||||
|
||||
|
||||
/**
|
||||
Broadcast COND_refresh and COND_global_read_lock.
|
||||
Broadcast COND_global_read_lock.
|
||||
|
||||
Due to a bug in a threading library it could happen that a signal
|
||||
did not reach its target. A condition for this was that the same
|
||||
condition variable was used with different mutexes in
|
||||
mysql_cond_wait(). Some time ago we changed LOCK_open to
|
||||
LOCK_global_read_lock in global read lock handling. So COND_refresh
|
||||
was used with LOCK_open and LOCK_global_read_lock.
|
||||
|
||||
We did now also change from COND_refresh to COND_global_read_lock
|
||||
in global read lock handling. But now it is necessary to signal
|
||||
both conditions at the same time.
|
||||
|
||||
@note
|
||||
When signalling COND_global_read_lock within the global read lock
|
||||
handling, it is not necessary to also signal COND_refresh.
|
||||
TODO/FIXME: Dmitry thinks that we broadcast on COND_global_read_lock
|
||||
when old instance of table is closed to avoid races
|
||||
between incrementing refresh_version and
|
||||
wait_if_global_read_lock(thd, TRUE, FALSE) call.
|
||||
Once global read lock implementation starts using MDL
|
||||
infrastructure this will became unnecessary and should
|
||||
be removed.
|
||||
*/
|
||||
|
||||
void broadcast_refresh(void)
|
||||
{
|
||||
mysql_cond_broadcast(&COND_refresh);
|
||||
mysql_cond_broadcast(&COND_global_read_lock);
|
||||
}
|
||||
|
||||
|
42
sql/lock.h
42
sql/lock.h
@ -9,48 +9,6 @@ struct TABLE_LIST;
|
||||
class THD;
|
||||
typedef struct st_mysql_lock MYSQL_LOCK;
|
||||
|
||||
/* mysql_lock_tables() and open_table() flags bits */
|
||||
#define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK 0x0001
|
||||
#define MYSQL_OPEN_IGNORE_FLUSH 0x0002
|
||||
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0004
|
||||
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008
|
||||
#define MYSQL_LOCK_LOG_TABLE 0x0010
|
||||
/**
|
||||
Do not try to acquire a metadata lock on the table: we
|
||||
already have one.
|
||||
*/
|
||||
#define MYSQL_OPEN_HAS_MDL_LOCK 0x0020
|
||||
/**
|
||||
If in locked tables mode, ignore the locked tables and get
|
||||
a new instance of the table.
|
||||
*/
|
||||
#define MYSQL_OPEN_GET_NEW_TABLE 0x0040
|
||||
/** Don't look up the table in the list of temporary tables. */
|
||||
#define MYSQL_OPEN_SKIP_TEMPORARY 0x0080
|
||||
/** Fail instead of waiting when conficting metadata lock is discovered. */
|
||||
#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100
|
||||
/** Open tables using MDL_SHARED lock instead of one specified in parser. */
|
||||
#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0200
|
||||
/**
|
||||
Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified
|
||||
in parser.
|
||||
*/
|
||||
#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0400
|
||||
/**
|
||||
When opening or locking the table, use the maximum timeout
|
||||
(LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
|
||||
*/
|
||||
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800
|
||||
|
||||
/** Please refer to the internals manual. */
|
||||
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
||||
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\
|
||||
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\
|
||||
MYSQL_LOCK_IGNORE_TIMEOUT |\
|
||||
MYSQL_OPEN_GET_NEW_TABLE |\
|
||||
MYSQL_OPEN_SKIP_TEMPORARY |\
|
||||
MYSQL_OPEN_HAS_MDL_LOCK)
|
||||
|
||||
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags);
|
||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||
|
206
sql/mdl.cc
206
sql/mdl.cc
@ -71,6 +71,21 @@ static void init_mdl_psi_keys(void)
|
||||
void notify_shared_lock(THD *thd, MDL_ticket *conflicting_ticket);
|
||||
|
||||
|
||||
/**
|
||||
Thread state names to be used in case when we have to wait on resource
|
||||
belonging to certain namespace.
|
||||
*/
|
||||
|
||||
const char *MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]=
|
||||
{
|
||||
"Waiting for global metadata lock",
|
||||
"Waiting for schema metadata lock",
|
||||
"Waiting for table metadata lock",
|
||||
"Waiting for stored function metadata lock",
|
||||
"Waiting for stored procedure metadata lock",
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool mdl_initialized= 0;
|
||||
|
||||
|
||||
@ -98,38 +113,32 @@ private:
|
||||
};
|
||||
|
||||
|
||||
enum enum_deadlock_weight
|
||||
{
|
||||
MDL_DEADLOCK_WEIGHT_DML= 0,
|
||||
MDL_DEADLOCK_WEIGHT_DDL= 100
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A context of the recursive traversal through all contexts
|
||||
in all sessions in search for deadlock.
|
||||
*/
|
||||
|
||||
class Deadlock_detection_visitor
|
||||
class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor
|
||||
{
|
||||
public:
|
||||
Deadlock_detection_visitor(MDL_context *start_node_arg)
|
||||
: m_start_node(start_node_arg),
|
||||
m_victim(NULL),
|
||||
m_current_search_depth(0)
|
||||
m_current_search_depth(0),
|
||||
m_found_deadlock(FALSE)
|
||||
{}
|
||||
bool enter_node(MDL_context * /* unused */);
|
||||
void leave_node(MDL_context * /* unused */);
|
||||
virtual bool enter_node(MDL_context *node);
|
||||
virtual void leave_node(MDL_context *node);
|
||||
|
||||
bool inspect_edge(MDL_context *dest);
|
||||
virtual bool inspect_edge(MDL_context *dest);
|
||||
|
||||
MDL_context *get_victim() const { return m_victim; }
|
||||
|
||||
private:
|
||||
/**
|
||||
Change the deadlock victim to a new one if it has lower deadlock
|
||||
weight.
|
||||
*/
|
||||
MDL_context *opt_change_victim_to(MDL_context *new_victim);
|
||||
void opt_change_victim_to(MDL_context *new_victim);
|
||||
private:
|
||||
/**
|
||||
The context which has initiated the search. There
|
||||
@ -145,6 +154,8 @@ private:
|
||||
loop.
|
||||
*/
|
||||
uint m_current_search_depth;
|
||||
/** TRUE if we found a deadlock. */
|
||||
bool m_found_deadlock;
|
||||
/**
|
||||
Maximum depth for deadlock searches. After this depth is
|
||||
achieved we will unconditionally declare that there is a
|
||||
@ -167,29 +178,38 @@ private:
|
||||
a node is entered, inspect_edge() will be called
|
||||
for all wait-for destinations of this node. Then
|
||||
leave_node() will be called.
|
||||
We call "enter_node()" for all nodes we inspect,
|
||||
We call "enter_node()" for all nodes we inspect,
|
||||
including the starting node.
|
||||
|
||||
@retval TRUE Maximum search depth exceeded.
|
||||
@retval FALSE OK.
|
||||
*/
|
||||
|
||||
bool Deadlock_detection_visitor::enter_node(MDL_context * /* unused */)
|
||||
bool Deadlock_detection_visitor::enter_node(MDL_context *node)
|
||||
{
|
||||
if (++m_current_search_depth >= MAX_SEARCH_DEPTH)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
|
||||
if (m_found_deadlock)
|
||||
{
|
||||
DBUG_ASSERT(! m_victim);
|
||||
opt_change_victim_to(node);
|
||||
}
|
||||
return m_found_deadlock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Done inspecting this node. Decrease the search
|
||||
depth. Clear the node for debug safety.
|
||||
depth. If a deadlock is found, and we are
|
||||
backtracking to the start node, optionally
|
||||
change the deadlock victim to one with lower
|
||||
deadlock weight.
|
||||
*/
|
||||
|
||||
void Deadlock_detection_visitor::leave_node(MDL_context * /* unused */)
|
||||
void Deadlock_detection_visitor::leave_node(MDL_context *node)
|
||||
{
|
||||
--m_current_search_depth;
|
||||
if (m_found_deadlock)
|
||||
opt_change_victim_to(node);
|
||||
}
|
||||
|
||||
|
||||
@ -202,7 +222,8 @@ void Deadlock_detection_visitor::leave_node(MDL_context * /* unused */)
|
||||
|
||||
bool Deadlock_detection_visitor::inspect_edge(MDL_context *node)
|
||||
{
|
||||
return node == m_start_node;
|
||||
m_found_deadlock= node == m_start_node;
|
||||
return m_found_deadlock;
|
||||
}
|
||||
|
||||
|
||||
@ -214,7 +235,7 @@ bool Deadlock_detection_visitor::inspect_edge(MDL_context *node)
|
||||
@retval !new_victim New victim became the current.
|
||||
*/
|
||||
|
||||
MDL_context *
|
||||
void
|
||||
Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
|
||||
{
|
||||
if (m_victim == NULL ||
|
||||
@ -223,10 +244,10 @@ Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
|
||||
/* Swap victims, unlock the old one. */
|
||||
MDL_context *tmp= m_victim;
|
||||
m_victim= new_victim;
|
||||
return tmp;
|
||||
m_victim->lock_deadlock_victim();
|
||||
if (tmp)
|
||||
tmp->unlock_deadlock_victim();
|
||||
}
|
||||
/* No change, unlock the current context. */
|
||||
return new_victim;
|
||||
}
|
||||
|
||||
|
||||
@ -349,8 +370,8 @@ public:
|
||||
|
||||
void remove_ticket(Ticket_list MDL_lock::*queue, MDL_ticket *ticket);
|
||||
|
||||
bool find_deadlock(MDL_ticket *waiting_ticket,
|
||||
Deadlock_detection_visitor *dvisitor);
|
||||
bool visit_subgraph(MDL_ticket *waiting_ticket,
|
||||
MDL_wait_for_graph_visitor *gvisitor);
|
||||
|
||||
/** List of granted tickets for this lock. */
|
||||
Ticket_list m_granted;
|
||||
@ -479,14 +500,6 @@ mdl_locks_key(const uchar *record, size_t *length,
|
||||
the associated condition variable: LOCK_mdl and COND_mdl.
|
||||
These locking primitives are implementation details of the MDL
|
||||
subsystem and are private to it.
|
||||
|
||||
Note, that even though the new implementation adds acquisition
|
||||
of a new global mutex to the execution flow of almost every SQL
|
||||
statement, the design capitalizes on that to later save on
|
||||
look ups in the table definition cache. This leads to reduced
|
||||
contention overall and on LOCK_open in particular.
|
||||
Please see the description of MDL_context::acquire_lock()
|
||||
for details.
|
||||
*/
|
||||
|
||||
void mdl_init()
|
||||
@ -876,8 +889,8 @@ void MDL_ticket::destroy(MDL_ticket *ticket)
|
||||
uint MDL_ticket::get_deadlock_weight() const
|
||||
{
|
||||
return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
|
||||
m_type > MDL_SHARED_NO_WRITE ?
|
||||
MDL_DEADLOCK_WEIGHT_DDL : MDL_DEADLOCK_WEIGHT_DML);
|
||||
m_type >= MDL_SHARED_NO_WRITE ?
|
||||
DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML);
|
||||
}
|
||||
|
||||
|
||||
@ -946,17 +959,18 @@ void MDL_wait::reset_status()
|
||||
Wait for the status to be assigned to this wait slot.
|
||||
|
||||
@param abs_timeout Absolute time after which waiting should stop.
|
||||
@param set_status_on_tiemout TRUE - If in case of timeout waiting
|
||||
context should close the wait slot by
|
||||
sending TIMEOUT to itself.
|
||||
FALSE - Otherwise.
|
||||
@param set_status_on_timeout TRUE - If in case of timeout waiting
|
||||
context should close the wait slot by
|
||||
sending TIMEOUT to itself.
|
||||
FALSE - Otherwise.
|
||||
@param wait_state_name Thread state name to be set for duration of wait.
|
||||
|
||||
@returns Signal posted.
|
||||
*/
|
||||
|
||||
MDL_wait::enum_wait_status
|
||||
MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout,
|
||||
bool set_status_on_timeout)
|
||||
bool set_status_on_timeout, const char *wait_state_name)
|
||||
{
|
||||
const char *old_msg;
|
||||
enum_wait_status result;
|
||||
@ -965,7 +979,7 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout,
|
||||
mysql_mutex_lock(&m_LOCK_wait_status);
|
||||
|
||||
old_msg= thd_enter_cond(thd, &m_COND_wait_status, &m_LOCK_wait_status,
|
||||
"Waiting for table");
|
||||
wait_state_name);
|
||||
|
||||
while (!m_wait_status && !thd_killed(thd) &&
|
||||
wait_result != ETIMEDOUT && wait_result != ETIME)
|
||||
@ -1380,6 +1394,15 @@ bool MDL_lock::has_pending_conflicting_lock(enum_mdl_type type)
|
||||
}
|
||||
|
||||
|
||||
MDL_wait_for_graph_visitor::~MDL_wait_for_graph_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MDL_wait_for_subgraph::~MDL_wait_for_subgraph()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Check if ticket represents metadata lock of "stronger" or equal type
|
||||
than specified one. I.e. if metadata lock represented by ticket won't
|
||||
@ -1528,9 +1551,8 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
|
||||
MDL_ticket *ticket;
|
||||
bool is_transactional;
|
||||
|
||||
DBUG_ASSERT(mdl_request->type < MDL_SHARED_NO_WRITE ||
|
||||
(is_lock_owner(MDL_key::GLOBAL, "", "",
|
||||
MDL_INTENTION_EXCLUSIVE)));
|
||||
DBUG_ASSERT(mdl_request->type != MDL_EXCLUSIVE ||
|
||||
is_lock_owner(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE));
|
||||
DBUG_ASSERT(mdl_request->ticket == NULL);
|
||||
|
||||
/* Don't take chances in production. */
|
||||
@ -1746,7 +1768,8 @@ MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
|
||||
while (cmp_timespec(abs_shortwait, abs_timeout) <= 0)
|
||||
{
|
||||
/* abs_timeout is far away. Wait a short while and notify locks. */
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_shortwait, FALSE);
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_shortwait, FALSE,
|
||||
mdl_request->key.get_wait_state_name());
|
||||
|
||||
if (wait_status != MDL_wait::EMPTY)
|
||||
break;
|
||||
@ -1757,10 +1780,12 @@ MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
|
||||
set_timespec(abs_shortwait, 1);
|
||||
}
|
||||
if (wait_status == MDL_wait::EMPTY)
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE);
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE,
|
||||
mdl_request->key.get_wait_state_name());
|
||||
}
|
||||
else
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE);
|
||||
wait_status= m_wait.timed_wait(m_thd, &abs_timeout, TRUE,
|
||||
mdl_request->key.get_wait_state_name());
|
||||
|
||||
done_waiting_for();
|
||||
|
||||
@ -1952,8 +1977,17 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
|
||||
}
|
||||
|
||||
|
||||
bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
Deadlock_detection_visitor *dvisitor)
|
||||
/**
|
||||
A fragment of recursive traversal of the wait-for graph
|
||||
in search for deadlocks. Direct the deadlock visitor to all
|
||||
contexts that own the lock the current node in the wait-for
|
||||
graph is waiting for.
|
||||
As long as the initial node is remembered in the visitor,
|
||||
a deadlock is found when the same node is seen twice.
|
||||
*/
|
||||
|
||||
bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket,
|
||||
MDL_wait_for_graph_visitor *gvisitor)
|
||||
{
|
||||
MDL_ticket *ticket;
|
||||
MDL_context *src_ctx= waiting_ticket->get_ctx();
|
||||
@ -2022,7 +2056,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
are visiting it but this is OK: in the worst case we might do some
|
||||
extra work and one more context might be chosen as a victim.
|
||||
*/
|
||||
if (dvisitor->enter_node(src_ctx))
|
||||
if (gvisitor->enter_node(src_ctx))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
@ -2036,7 +2070,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
/* Filter out edges that point to the same node. */
|
||||
if (ticket->get_ctx() != src_ctx &&
|
||||
ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
|
||||
dvisitor->inspect_edge(ticket->get_ctx()))
|
||||
gvisitor->inspect_edge(ticket->get_ctx()))
|
||||
{
|
||||
goto end_leave_node;
|
||||
}
|
||||
@ -2047,7 +2081,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
/* Filter out edges that point to the same node. */
|
||||
if (ticket->get_ctx() != src_ctx &&
|
||||
ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
|
||||
dvisitor->inspect_edge(ticket->get_ctx()))
|
||||
gvisitor->inspect_edge(ticket->get_ctx()))
|
||||
{
|
||||
goto end_leave_node;
|
||||
}
|
||||
@ -2059,7 +2093,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
{
|
||||
if (ticket->get_ctx() != src_ctx &&
|
||||
ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
|
||||
ticket->get_ctx()->find_deadlock(dvisitor))
|
||||
ticket->get_ctx()->visit_subgraph(gvisitor))
|
||||
{
|
||||
goto end_leave_node;
|
||||
}
|
||||
@ -2070,7 +2104,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
{
|
||||
if (ticket->get_ctx() != src_ctx &&
|
||||
ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
|
||||
ticket->get_ctx()->find_deadlock(dvisitor))
|
||||
ticket->get_ctx()->visit_subgraph(gvisitor))
|
||||
{
|
||||
goto end_leave_node;
|
||||
}
|
||||
@ -2079,7 +2113,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
result= FALSE;
|
||||
|
||||
end_leave_node:
|
||||
dvisitor->leave_node(src_ctx);
|
||||
gvisitor->leave_node(src_ctx);
|
||||
|
||||
end:
|
||||
mysql_prlock_unlock(&m_rwlock);
|
||||
@ -2088,35 +2122,47 @@ end:
|
||||
|
||||
|
||||
/**
|
||||
Recursively traverse the wait-for graph of MDL contexts
|
||||
in search for deadlocks.
|
||||
Traverse a portion of wait-for graph which is reachable
|
||||
through the edge represented by this ticket and search
|
||||
for deadlocks.
|
||||
|
||||
@retval TRUE A deadlock is found. A victim is remembered
|
||||
by the visitor.
|
||||
@retval TRUE A deadlock is found. A pointer to deadlock
|
||||
victim is saved in the visitor.
|
||||
@retval FALSE
|
||||
*/
|
||||
|
||||
bool MDL_context::find_deadlock(Deadlock_detection_visitor *dvisitor)
|
||||
bool MDL_ticket::accept_visitor(MDL_wait_for_graph_visitor *gvisitor)
|
||||
{
|
||||
return m_lock->visit_subgraph(this, gvisitor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A fragment of recursive traversal of the wait-for graph of
|
||||
MDL contexts in the server in search for deadlocks.
|
||||
Assume this MDL context is a node in the wait-for graph,
|
||||
and direct the visitor to all adjacent nodes. As long
|
||||
as the starting node is remembered in the visitor, a
|
||||
deadlock is found when the same node is visited twice.
|
||||
One MDL context is connected to another in the wait-for
|
||||
graph if it waits on a resource that is held by the other
|
||||
context.
|
||||
|
||||
@retval TRUE A deadlock is found. A pointer to deadlock
|
||||
victim is saved in the visitor.
|
||||
@retval FALSE
|
||||
*/
|
||||
|
||||
bool MDL_context::visit_subgraph(MDL_wait_for_graph_visitor *gvisitor)
|
||||
{
|
||||
MDL_context *m_unlock_ctx= this;
|
||||
bool result= FALSE;
|
||||
|
||||
mysql_prlock_rdlock(&m_LOCK_waiting_for);
|
||||
|
||||
if (m_waiting_for)
|
||||
{
|
||||
result= m_waiting_for->m_lock->find_deadlock(m_waiting_for, dvisitor);
|
||||
if (result)
|
||||
m_unlock_ctx= dvisitor->opt_change_victim_to(this);
|
||||
}
|
||||
/*
|
||||
We may recurse into the same MDL_context more than once
|
||||
in case this is not the starting node. Make sure we release the
|
||||
read lock as it's been taken, except for 1 read lock for
|
||||
the deadlock victim.
|
||||
*/
|
||||
if (m_unlock_ctx)
|
||||
mysql_prlock_unlock(&m_unlock_ctx->m_LOCK_waiting_for);
|
||||
result= m_waiting_for->accept_visitor(gvisitor);
|
||||
|
||||
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2138,14 +2184,14 @@ void MDL_context::find_deadlock()
|
||||
while (1)
|
||||
{
|
||||
/*
|
||||
The fact that we use fresh instance of dvisitor for each
|
||||
The fact that we use fresh instance of gvisitor for each
|
||||
search performed by find_deadlock() below is important,
|
||||
the code responsible for victim selection relies on this.
|
||||
*/
|
||||
Deadlock_detection_visitor dvisitor(this);
|
||||
MDL_context *victim;
|
||||
|
||||
if (! find_deadlock(&dvisitor))
|
||||
if (! visit_subgraph(&dvisitor))
|
||||
{
|
||||
/* No deadlocks are found! */
|
||||
break;
|
||||
@ -2166,7 +2212,7 @@ void MDL_context::find_deadlock()
|
||||
context was waiting is concurrently satisfied.
|
||||
*/
|
||||
(void) victim->m_wait.set_status(MDL_wait::VICTIM);
|
||||
mysql_prlock_unlock(&victim->m_LOCK_waiting_for);
|
||||
victim->unlock_deadlock_victim();
|
||||
|
||||
if (victim == this)
|
||||
break;
|
||||
|
99
sql/mdl.h
99
sql/mdl.h
@ -34,7 +34,6 @@ class THD;
|
||||
class MDL_context;
|
||||
class MDL_lock;
|
||||
class MDL_ticket;
|
||||
class Deadlock_detection_visitor;
|
||||
|
||||
/**
|
||||
Type of metadata lock request.
|
||||
@ -184,7 +183,9 @@ public:
|
||||
TABLE,
|
||||
FUNCTION,
|
||||
PROCEDURE,
|
||||
TRIGGER };
|
||||
TRIGGER,
|
||||
/* This should be the last ! */
|
||||
NAMESPACE_END };
|
||||
|
||||
const uchar *ptr() const { return (uchar*) m_ptr; }
|
||||
uint length() const { return m_length; }
|
||||
@ -251,10 +252,20 @@ public:
|
||||
}
|
||||
MDL_key() {} /* To use when part of MDL_request. */
|
||||
|
||||
/**
|
||||
Get thread state name to be used in case when we have to
|
||||
wait on resource identified by key.
|
||||
*/
|
||||
const char * get_wait_state_name() const
|
||||
{
|
||||
return m_namespace_to_wait_state_name[(int)mdl_namespace()];
|
||||
}
|
||||
|
||||
private:
|
||||
uint16 m_length;
|
||||
uint16 m_db_name_length;
|
||||
char m_ptr[MAX_MDLKEY_LENGTH];
|
||||
static const char * m_namespace_to_wait_state_name[NAMESPACE_END];
|
||||
private:
|
||||
MDL_key(const MDL_key &); /* not implemented */
|
||||
MDL_key &operator=(const MDL_key &); /* not implemented */
|
||||
@ -360,6 +371,59 @@ public:
|
||||
|
||||
typedef void (*mdl_cached_object_release_hook)(void *);
|
||||
|
||||
|
||||
/**
|
||||
An abstract class for inspection of a connected
|
||||
subgraph of the wait-for graph.
|
||||
*/
|
||||
|
||||
class MDL_wait_for_graph_visitor
|
||||
{
|
||||
public:
|
||||
virtual bool enter_node(MDL_context *node) = 0;
|
||||
virtual void leave_node(MDL_context *node) = 0;
|
||||
|
||||
virtual bool inspect_edge(MDL_context *dest) = 0;
|
||||
virtual ~MDL_wait_for_graph_visitor();
|
||||
MDL_wait_for_graph_visitor() :m_lock_open_count(0) {}
|
||||
public:
|
||||
/**
|
||||
XXX, hack: During deadlock search, we may need to
|
||||
inspect TABLE_SHAREs and acquire LOCK_open. Since
|
||||
LOCK_open is not a recursive mutex, count here how many
|
||||
times we "took" it (but only take and release once).
|
||||
Not using a native recursive mutex or rwlock in 5.5 for
|
||||
LOCK_open since it has significant performance impacts.
|
||||
*/
|
||||
uint m_lock_open_count;
|
||||
};
|
||||
|
||||
/**
|
||||
Abstract class representing an edge in the waiters graph
|
||||
to be traversed by deadlock detection algorithm.
|
||||
*/
|
||||
|
||||
class MDL_wait_for_subgraph
|
||||
{
|
||||
public:
|
||||
virtual ~MDL_wait_for_subgraph();
|
||||
|
||||
/**
|
||||
Accept a wait-for graph visitor to inspect the node
|
||||
this edge is leading to.
|
||||
*/
|
||||
virtual bool accept_visitor(MDL_wait_for_graph_visitor *gvisitor) = 0;
|
||||
|
||||
enum enum_deadlock_weight
|
||||
{
|
||||
DEADLOCK_WEIGHT_DML= 0,
|
||||
DEADLOCK_WEIGHT_DDL= 100
|
||||
};
|
||||
/* A helper used to determine which lock request should be aborted. */
|
||||
virtual uint get_deadlock_weight() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A granted metadata lock.
|
||||
|
||||
@ -380,7 +444,7 @@ typedef void (*mdl_cached_object_release_hook)(void *);
|
||||
threads/contexts.
|
||||
*/
|
||||
|
||||
class MDL_ticket
|
||||
class MDL_ticket : public MDL_wait_for_subgraph
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@ -414,8 +478,9 @@ public:
|
||||
bool is_incompatible_when_granted(enum_mdl_type type) const;
|
||||
bool is_incompatible_when_waiting(enum_mdl_type type) const;
|
||||
|
||||
/* A helper used to determine which lock request should be aborted. */
|
||||
uint get_deadlock_weight() const;
|
||||
/** Implement MDL_wait_for_subgraph interface. */
|
||||
virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor);
|
||||
virtual uint get_deadlock_weight() const;
|
||||
private:
|
||||
friend class MDL_context;
|
||||
|
||||
@ -462,7 +527,7 @@ public:
|
||||
enum_wait_status get_status();
|
||||
void reset_status();
|
||||
enum_wait_status timed_wait(THD *thd, struct timespec *abs_timeout,
|
||||
bool signal_timeout);
|
||||
bool signal_timeout, const char *wait_state_name);
|
||||
private:
|
||||
/**
|
||||
Condvar which is used for waiting until this context's pending
|
||||
@ -582,8 +647,6 @@ public:
|
||||
{
|
||||
return m_needs_thr_lock_abort;
|
||||
}
|
||||
|
||||
bool find_deadlock(Deadlock_detection_visitor *dvisitor);
|
||||
public:
|
||||
/**
|
||||
If our request for a lock is scheduled, or aborted by the deadlock
|
||||
@ -675,12 +738,13 @@ private:
|
||||
*/
|
||||
mysql_prlock_t m_LOCK_waiting_for;
|
||||
/**
|
||||
Tell the deadlock detector what lock this session is waiting for.
|
||||
Tell the deadlock detector what metadata lock or table
|
||||
definition cache entry this session is waiting for.
|
||||
In principle, this is redundant, as information can be found
|
||||
by inspecting waiting queues, but we'd very much like it to be
|
||||
readily available to the wait-for graph iterator.
|
||||
*/
|
||||
MDL_ticket *m_waiting_for;
|
||||
MDL_wait_for_subgraph *m_waiting_for;
|
||||
private:
|
||||
MDL_ticket *find_ticket(MDL_request *mdl_req,
|
||||
bool *is_transactional);
|
||||
@ -688,13 +752,16 @@ private:
|
||||
bool try_acquire_lock_impl(MDL_request *mdl_request,
|
||||
MDL_ticket **out_ticket);
|
||||
|
||||
public:
|
||||
void find_deadlock();
|
||||
|
||||
bool visit_subgraph(MDL_wait_for_graph_visitor *dvisitor);
|
||||
|
||||
/** Inform the deadlock detector there is an edge in the wait-for graph. */
|
||||
void will_wait_for(MDL_ticket *pending_ticket)
|
||||
void will_wait_for(MDL_wait_for_subgraph *waiting_for_arg)
|
||||
{
|
||||
mysql_prlock_wrlock(&m_LOCK_waiting_for);
|
||||
m_waiting_for= pending_ticket;
|
||||
m_waiting_for= waiting_for_arg;
|
||||
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||
}
|
||||
|
||||
@ -705,6 +772,14 @@ private:
|
||||
m_waiting_for= NULL;
|
||||
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||
}
|
||||
void lock_deadlock_victim()
|
||||
{
|
||||
mysql_prlock_rdlock(&m_LOCK_waiting_for);
|
||||
}
|
||||
void unlock_deadlock_victim()
|
||||
{
|
||||
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||
}
|
||||
private:
|
||||
MDL_context(const MDL_context &rhs); /* not implemented */
|
||||
MDL_context &operator=(MDL_context &rhs); /* not implemented */
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include <errmsg.h>
|
||||
#include "sp_rcontext.h"
|
||||
#include "sp_cache.h"
|
||||
#include "sql_reload.h" // reload_acl_and_cache
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
@ -601,7 +602,7 @@ SHOW_COMP_OPTION have_profiling;
|
||||
pthread_key(MEM_ROOT**,THR_MALLOC);
|
||||
pthread_key(THD*, THR_THD);
|
||||
mysql_mutex_t LOCK_thread_count;
|
||||
mysql_mutex_t LOCK_open,
|
||||
mysql_mutex_t
|
||||
LOCK_status, LOCK_global_read_lock,
|
||||
LOCK_error_log, LOCK_uuid_generator,
|
||||
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
|
||||
@ -623,7 +624,7 @@ mysql_mutex_t LOCK_des_key_file;
|
||||
mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
|
||||
mysql_rwlock_t LOCK_system_variables_hash;
|
||||
mysql_cond_t COND_thread_count;
|
||||
mysql_cond_t COND_refresh, COND_global_read_lock;
|
||||
mysql_cond_t COND_global_read_lock;
|
||||
pthread_t signal_thread;
|
||||
pthread_attr_t connection_attrib;
|
||||
mysql_mutex_t LOCK_server_started;
|
||||
@ -1526,7 +1527,6 @@ static void wait_for_signal_thread_to_end()
|
||||
static void clean_up_mutexes()
|
||||
{
|
||||
mysql_rwlock_destroy(&LOCK_grant);
|
||||
mysql_mutex_destroy(&LOCK_open);
|
||||
mysql_mutex_destroy(&LOCK_thread_count);
|
||||
mysql_mutex_destroy(&LOCK_status);
|
||||
mysql_mutex_destroy(&LOCK_delayed_insert);
|
||||
@ -1559,7 +1559,6 @@ static void clean_up_mutexes()
|
||||
mysql_mutex_destroy(&LOCK_prepared_stmt_count);
|
||||
mysql_mutex_destroy(&LOCK_error_messages);
|
||||
mysql_cond_destroy(&COND_thread_count);
|
||||
mysql_cond_destroy(&COND_refresh);
|
||||
mysql_cond_destroy(&COND_global_read_lock);
|
||||
mysql_cond_destroy(&COND_thread_cache);
|
||||
mysql_cond_destroy(&COND_flush_thread_cache);
|
||||
@ -3500,7 +3499,6 @@ You should consider changing lower_case_table_names to 1 or 2",
|
||||
|
||||
static int init_thread_environment()
|
||||
{
|
||||
mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
|
||||
mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
|
||||
mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
|
||||
mysql_mutex_init(key_LOCK_delayed_insert,
|
||||
@ -3547,7 +3545,6 @@ static int init_thread_environment()
|
||||
mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
|
||||
mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
|
||||
mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
|
||||
mysql_cond_init(key_COND_refresh, &COND_refresh, NULL);
|
||||
mysql_cond_init(key_COND_global_read_lock, &COND_global_read_lock, NULL);
|
||||
mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
|
||||
mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
|
||||
@ -7682,7 +7679,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
|
||||
key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
|
||||
key_LOCK_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables,
|
||||
key_LOCK_manager,
|
||||
key_LOCK_open, key_LOCK_prepared_stmt_count,
|
||||
key_LOCK_prepared_stmt_count,
|
||||
key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status,
|
||||
key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
|
||||
key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
|
||||
@ -7721,7 +7718,6 @@ static PSI_mutex_info all_server_mutexes[]=
|
||||
{ &key_LOCK_global_read_lock, "LOCK_global_read_lock", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL},
|
||||
@ -7769,7 +7765,7 @@ PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
|
||||
|
||||
PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond,
|
||||
key_COND_cache_status_changed, key_COND_global_read_lock, key_COND_manager,
|
||||
key_COND_refresh, key_COND_rpl_status, key_COND_server_started,
|
||||
key_COND_rpl_status, key_COND_server_started,
|
||||
key_delayed_insert_cond, key_delayed_insert_cond_client,
|
||||
key_item_func_sleep_cond, key_master_info_data_cond,
|
||||
key_master_info_start_cond, key_master_info_stop_cond,
|
||||
@ -7793,7 +7789,6 @@ static PSI_cond_info all_server_conds[]=
|
||||
{ &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
|
||||
{ &key_COND_global_read_lock, "COND_global_read_lock", PSI_FLAG_GLOBAL},
|
||||
{ &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
|
||||
{ &key_COND_refresh, "COND_refresh", PSI_FLAG_GLOBAL},
|
||||
{ &key_COND_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL},
|
||||
{ &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
|
||||
{ &key_delayed_insert_cond, "Delayed_insert::cond", 0},
|
||||
|
@ -229,7 +229,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
|
||||
key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
|
||||
key_LOCK_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables,
|
||||
key_LOCK_logger, key_LOCK_manager,
|
||||
key_LOCK_open, key_LOCK_prepared_stmt_count,
|
||||
key_LOCK_prepared_stmt_count,
|
||||
key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status,
|
||||
key_LOCK_table_share, key_LOCK_thd_data,
|
||||
key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
|
||||
@ -249,7 +249,7 @@ extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
|
||||
|
||||
extern PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond,
|
||||
key_COND_cache_status_changed, key_COND_global_read_lock, key_COND_manager,
|
||||
key_COND_refresh, key_COND_rpl_status, key_COND_server_started,
|
||||
key_COND_rpl_status, key_COND_server_started,
|
||||
key_delayed_insert_cond, key_delayed_insert_cond_client,
|
||||
key_item_func_sleep_cond, key_master_info_data_cond,
|
||||
key_master_info_start_cond, key_master_info_stop_cond,
|
||||
@ -316,7 +316,7 @@ extern MYSQL_PLUGIN_IMPORT key_map key_map_full; /* Should be threaded
|
||||
/*
|
||||
Server mutex locks and condition variables.
|
||||
*/
|
||||
extern mysql_mutex_t LOCK_open,
|
||||
extern mysql_mutex_t
|
||||
LOCK_user_locks, LOCK_status,
|
||||
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
||||
@ -332,7 +332,7 @@ extern mysql_cond_t COND_server_started;
|
||||
extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
|
||||
extern mysql_rwlock_t LOCK_system_variables_hash;
|
||||
extern mysql_cond_t COND_thread_count;
|
||||
extern mysql_cond_t COND_refresh, COND_manager;
|
||||
extern mysql_cond_t COND_manager;
|
||||
extern mysql_cond_t COND_global_read_lock;
|
||||
extern int32 thread_running;
|
||||
extern my_atomic_rwlock_t thread_running_lock;
|
||||
|
@ -95,20 +95,19 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
|
||||
&error, hash_value))))
|
||||
{
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
share= get_table_share(thd, table_list, key, key_length, 0,
|
||||
&error, hash_value);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
if (share == NULL)
|
||||
DBUG_RETURN(0); // Can't open frm file
|
||||
}
|
||||
|
||||
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
release_table_share(share);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(0); // Out of memory
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
table= &tmp_table;
|
||||
}
|
||||
|
||||
@ -772,10 +771,8 @@ send_result_message:
|
||||
}
|
||||
else if (open_for_modify || fatal_error)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||
table->db, table->table_name);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
table->db, table->table_name, FALSE);
|
||||
/*
|
||||
May be something modified. Consequently, we have to
|
||||
invalidate the query cache.
|
||||
|
663
sql/sql_base.cc
663
sql/sql_base.cc
File diff suppressed because it is too large
Load Diff
118
sql/sql_base.h
118
sql/sql_base.h
@ -70,6 +70,7 @@ enum enum_tdc_remove_table_type {TDC_RT_REMOVE_ALL, TDC_RT_REMOVE_NOT_OWN,
|
||||
#define RTFC_CHECK_KILLED_FLAG 0x0004
|
||||
|
||||
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
|
||||
extern mysql_mutex_t LOCK_open;
|
||||
bool table_cache_init(void);
|
||||
void table_cache_free(void);
|
||||
bool table_def_init(void);
|
||||
@ -88,21 +89,51 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name);
|
||||
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||
uint lock_flags);
|
||||
|
||||
/* mysql_lock_tables() and open_table() flags bits */
|
||||
#define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK 0x0001
|
||||
#define MYSQL_OPEN_IGNORE_FLUSH 0x0002
|
||||
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0004
|
||||
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008
|
||||
#define MYSQL_LOCK_LOG_TABLE 0x0010
|
||||
/**
|
||||
Do not try to acquire a metadata lock on the table: we
|
||||
already have one.
|
||||
*/
|
||||
#define MYSQL_OPEN_HAS_MDL_LOCK 0x0020
|
||||
/**
|
||||
If in locked tables mode, ignore the locked tables and get
|
||||
a new instance of the table.
|
||||
*/
|
||||
#define MYSQL_OPEN_GET_NEW_TABLE 0x0040
|
||||
/** Don't look up the table in the list of temporary tables. */
|
||||
#define MYSQL_OPEN_SKIP_TEMPORARY 0x0080
|
||||
/** Fail instead of waiting when conficting metadata lock is discovered. */
|
||||
#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100
|
||||
/** Open tables using MDL_SHARED lock instead of one specified in parser. */
|
||||
#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0200
|
||||
/**
|
||||
Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified
|
||||
in parser.
|
||||
*/
|
||||
#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0400
|
||||
/**
|
||||
When opening or locking the table, use the maximum timeout
|
||||
(LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
|
||||
*/
|
||||
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800
|
||||
|
||||
/** Please refer to the internals manual. */
|
||||
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
||||
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\
|
||||
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\
|
||||
MYSQL_LOCK_IGNORE_TIMEOUT |\
|
||||
MYSQL_OPEN_GET_NEW_TABLE |\
|
||||
MYSQL_OPEN_SKIP_TEMPORARY |\
|
||||
MYSQL_OPEN_HAS_MDL_LOCK)
|
||||
|
||||
bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
Open_table_context *ot_ctx);
|
||||
bool name_lock_locked_table(THD *thd, TABLE_LIST *tables);
|
||||
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in);
|
||||
TABLE *table_cache_insert_placeholder(THD *thd, const char *key,
|
||||
uint key_length);
|
||||
bool lock_table_name_if_not_cached(THD *thd, const char *db,
|
||||
const char *table_name, TABLE **table);
|
||||
void detach_merge_children(TABLE *table, bool clear_refs);
|
||||
bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
|
||||
TABLE_LIST *new_child_list, TABLE_LIST **new_last);
|
||||
bool reopen_table(TABLE *table);
|
||||
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
|
||||
void close_data_files_and_morph_locks(THD *thd, const char *db,
|
||||
const char *table_name);
|
||||
bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||
uint db_stat, uint prgflag,
|
||||
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
|
||||
@ -185,12 +216,9 @@ bool setup_tables_and_check_access(THD *thd,
|
||||
ulong want_access);
|
||||
bool wait_while_table_is_used(THD *thd, TABLE *table,
|
||||
enum ha_extra_function function);
|
||||
void unlink_open_table(THD *thd, TABLE *find, bool unlock);
|
||||
|
||||
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||
const char *table_name);
|
||||
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||
bool remove_from_locked_tables);
|
||||
void update_non_unique_table_error(TABLE_LIST *update,
|
||||
const char *operation,
|
||||
TABLE_LIST *duplicate);
|
||||
@ -226,8 +254,6 @@ void close_temporary_table(THD *thd, TABLE *table, bool free_share,
|
||||
void close_temporary(TABLE *table, bool free_share, bool delete_table);
|
||||
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
||||
const char *table_name);
|
||||
void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table);
|
||||
void remove_db_from_cache(const char *db);
|
||||
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
||||
|
||||
/* Functions to work with system tables. */
|
||||
@ -243,16 +269,15 @@ TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
|
||||
Open_tables_state *backup);
|
||||
void close_performance_schema_table(THD *thd, Open_tables_state *backup);
|
||||
|
||||
bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
|
||||
bool wait_for_refresh);
|
||||
bool close_cached_connection_tables(THD *thd, bool wait_for_refresh,
|
||||
LEX_STRING *connect_string,
|
||||
bool have_lock = FALSE);
|
||||
bool close_cached_tables(THD *thd, TABLE_LIST *tables,
|
||||
bool wait_for_refresh, ulong timeout);
|
||||
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
|
||||
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||
bool remove_from_locked_tables);
|
||||
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
|
||||
bool remove_table_from_cache(THD *thd, const char *db, const char *table,
|
||||
uint flags);
|
||||
void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
|
||||
const char *db, const char *table_name);
|
||||
const char *db, const char *table_name,
|
||||
bool has_lock);
|
||||
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||
char *cache_key, uint cache_key_length,
|
||||
MEM_ROOT *mem_root, uint flags);
|
||||
@ -263,12 +288,10 @@ TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
|
||||
void mark_tmp_table_for_reuse(TABLE *table);
|
||||
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
|
||||
|
||||
extern uint table_cache_count;
|
||||
extern TABLE *unused_tables;
|
||||
extern Item **not_found_item;
|
||||
extern Field *not_found_field;
|
||||
extern Field *view_ref_found;
|
||||
extern HASH open_cache;
|
||||
extern HASH table_def_cache;
|
||||
|
||||
/**
|
||||
@ -446,8 +469,8 @@ public:
|
||||
enum enum_open_table_action
|
||||
{
|
||||
OT_NO_ACTION= 0,
|
||||
OT_MDL_CONFLICT,
|
||||
OT_WAIT_TDC,
|
||||
OT_BACKOFF_AND_RETRY,
|
||||
OT_REOPEN_TABLES,
|
||||
OT_DISCOVER,
|
||||
OT_REPAIR
|
||||
};
|
||||
@ -457,9 +480,6 @@ public:
|
||||
bool request_backoff_action(enum_open_table_action action_arg,
|
||||
TABLE_LIST *table);
|
||||
|
||||
void add_request(MDL_request *request)
|
||||
{ m_mdl_requests.push_front(request); }
|
||||
|
||||
bool can_recover_from_failed_open() const
|
||||
{ return m_action != OT_NO_ACTION; }
|
||||
|
||||
@ -481,8 +501,6 @@ public:
|
||||
|
||||
uint get_flags() const { return m_flags; }
|
||||
private:
|
||||
/** List of requests for all locks taken so far. Used for waiting on locks. */
|
||||
MDL_request_list m_mdl_requests;
|
||||
/**
|
||||
For OT_DISCOVER and OT_REPAIR actions, the table list element for
|
||||
the table which definition should be re-discovered or which
|
||||
@ -508,4 +526,34 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
This internal handler is used to trap ER_NO_SUCH_TABLE.
|
||||
*/
|
||||
|
||||
class No_such_table_error_handler : public Internal_error_handler
|
||||
{
|
||||
public:
|
||||
No_such_table_error_handler()
|
||||
: m_handled_errors(0), m_unhandled_errors(0)
|
||||
{}
|
||||
|
||||
bool handle_condition(THD *thd,
|
||||
uint sql_errno,
|
||||
const char* sqlstate,
|
||||
MYSQL_ERROR::enum_warning_level level,
|
||||
const char* msg,
|
||||
MYSQL_ERROR ** cond_hdl);
|
||||
|
||||
/**
|
||||
Returns TRUE if one or more ER_NO_SUCH_TABLE errors have been
|
||||
trapped and no other errors have been seen. FALSE otherwise.
|
||||
*/
|
||||
bool safely_trapped_errors();
|
||||
|
||||
private:
|
||||
int m_handled_errors;
|
||||
int m_unhandled_errors;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SQL_BASE_INCLUDED */
|
||||
|
@ -934,7 +934,7 @@ void mysql_ha_flush(THD *thd)
|
||||
((hash_tables->table->mdl_ticket &&
|
||||
hash_tables->table->mdl_ticket->has_pending_conflicting_lock()) ||
|
||||
(!hash_tables->table->s->tmp_table &&
|
||||
hash_tables->table->s->needs_reopen())))
|
||||
hash_tables->table->s->has_old_version())))
|
||||
mysql_ha_close_table(thd, hash_tables);
|
||||
}
|
||||
|
||||
|
@ -2705,7 +2705,7 @@ bool Delayed_insert::handle_inserts(void)
|
||||
|
||||
thd_proc_info(&thd, "insert");
|
||||
max_rows= delayed_insert_limit;
|
||||
if (thd.killed || table->s->needs_reopen())
|
||||
if (thd.killed || table->s->has_old_version())
|
||||
{
|
||||
thd.killed= THD::KILL_CONNECTION;
|
||||
max_rows= ULONG_MAX; // Do as much as possible
|
||||
@ -3592,11 +3592,9 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
*/
|
||||
if (open_table(thd, create_table, thd->mem_root, &ot_ctx))
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
quick_rm_table(create_info->db_type, create_table->db,
|
||||
table_case_name(create_info, create_table->table_name),
|
||||
0);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
else
|
||||
table= create_table->table;
|
||||
|
393
sql/sql_parse.cc
393
sql/sql_parse.cc
@ -50,6 +50,7 @@
|
||||
// mysql_backup_table,
|
||||
// mysql_restore_table
|
||||
#include "sql_truncate.h" // mysql_truncate_table
|
||||
#include "sql_reload.h" // reload_acl_and_cache
|
||||
#include "sql_admin.h" // mysql_assign_to_keycache
|
||||
#include "sql_connect.h" // check_user,
|
||||
// decrease_user_connections,
|
||||
@ -1695,140 +1696,6 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Implementation of FLUSH TABLES <table_list> WITH READ LOCK.
|
||||
|
||||
In brief: take exclusive locks, expel tables from the table
|
||||
cache, reopen the tables, enter the 'LOCKED TABLES' mode,
|
||||
downgrade the locks.
|
||||
Note: the function is written to be called from
|
||||
mysql_execute_command(), it is not reusable in arbitrary
|
||||
execution context.
|
||||
|
||||
Required privileges
|
||||
-------------------
|
||||
Since the statement implicitly enters LOCK TABLES mode,
|
||||
it requires LOCK TABLES privilege on every table.
|
||||
But since the rest of FLUSH commands require
|
||||
the global RELOAD_ACL, it also requires RELOAD_ACL.
|
||||
|
||||
Compatibility with the global read lock
|
||||
---------------------------------------
|
||||
We don't wait for the GRL, since neither the
|
||||
5.1 combination that this new statement is intended to
|
||||
replace (LOCK TABLE <list> WRITE; FLUSH TABLES;),
|
||||
nor FLUSH TABLES WITH READ LOCK do.
|
||||
@todo: this is not implemented, Dmitry disagrees.
|
||||
Currently we wait for GRL in another connection,
|
||||
but are compatible with a GRL in our own connection.
|
||||
|
||||
Behaviour under LOCK TABLES
|
||||
---------------------------
|
||||
Bail out: i.e. don't perform an implicit UNLOCK TABLES.
|
||||
This is not consistent with LOCK TABLES statement, but is
|
||||
in line with behaviour of FLUSH TABLES WITH READ LOCK, and we
|
||||
try to not introduce any new statements with implicit
|
||||
semantics.
|
||||
|
||||
Compatibility with parallel updates
|
||||
-----------------------------------
|
||||
As a result, we will wait for all open transactions
|
||||
against the tables to complete. After the lock downgrade,
|
||||
new transactions will be able to read the tables, but not
|
||||
write to them.
|
||||
|
||||
Differences from FLUSH TABLES <list>
|
||||
-------------------------------------
|
||||
- you can't flush WITH READ LOCK a non-existent table
|
||||
- you can't flush WITH READ LOCK under LOCK TABLES
|
||||
- currently incompatible with the GRL (@todo: fix)
|
||||
|
||||
Effect on views and temporary tables.
|
||||
------------------------------------
|
||||
You can only apply this command to existing base tables.
|
||||
If a view with such name exists, ER_WRONG_OBJECT is returned.
|
||||
If a temporary table with such name exists, it's ignored:
|
||||
if there is a base table, it's used, otherwise ER_NO_SUCH_TABLE
|
||||
is returned.
|
||||
*/
|
||||
|
||||
static bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
||||
{
|
||||
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
|
||||
TABLE_LIST *table_list;
|
||||
|
||||
/*
|
||||
This is called from SQLCOM_FLUSH, the transaction has
|
||||
been committed implicitly.
|
||||
*/
|
||||
|
||||
/* RELOAD_ACL is checked by the caller. Check table-level privileges. */
|
||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
@todo: Since lock_table_names() acquires a global IX
|
||||
lock, this actually waits for a GRL in another connection.
|
||||
We are thus introducing an incompatibility.
|
||||
Do nothing for now, since not taking a global IX violates
|
||||
current internal MDL asserts, fix after discussing with
|
||||
Dmitry.
|
||||
*/
|
||||
if (lock_table_names(thd, all_tables, 0, thd->variables.lock_wait_timeout,
|
||||
MYSQL_OPEN_SKIP_TEMPORARY))
|
||||
goto error;
|
||||
|
||||
for (table_list= all_tables; table_list;
|
||||
table_list= table_list->next_global)
|
||||
{
|
||||
/* Remove the table from cache. */
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
|
||||
table_list->db,
|
||||
table_list->table_name);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
/* Skip views and temporary tables. */
|
||||
table_list->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
|
||||
table_list->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
|
||||
}
|
||||
|
||||
if (open_and_lock_tables(thd, all_tables, FALSE,
|
||||
MYSQL_OPEN_HAS_MDL_LOCK,
|
||||
&lock_tables_prelocking_strategy) ||
|
||||
thd->locked_tables_list.init_locked_tables(thd))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
thd->variables.option_bits|= OPTION_TABLE_LOCK;
|
||||
|
||||
/*
|
||||
Downgrade the exclusive locks.
|
||||
Use MDL_SHARED_NO_WRITE as the intended
|
||||
post effect of this call is identical
|
||||
to LOCK TABLES <...> READ, and we didn't use
|
||||
thd->in_lock_talbes and thd->sql_command= SQLCOM_LOCK_TABLES
|
||||
hacks to enter the LTM.
|
||||
@todo: release the global IX lock here!!!
|
||||
*/
|
||||
for (table_list= all_tables; table_list;
|
||||
table_list= table_list->next_global)
|
||||
table_list->mdl_request.ticket->downgrade_exclusive_lock(MDL_SHARED_NO_WRITE);
|
||||
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read query from packet and store in thd->query.
|
||||
Used in COM_QUERY and COM_STMT_PREPARE.
|
||||
@ -3226,7 +3093,7 @@ end_with_restore_list:
|
||||
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
||||
}
|
||||
/* DDL and binlog write order protected by LOCK_open */
|
||||
/* DDL and binlog write order are protected by metadata locks. */
|
||||
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
|
||||
lex->drop_temporary);
|
||||
}
|
||||
@ -3771,6 +3638,10 @@ end_with_restore_list:
|
||||
|
||||
if (first_table && lex->type & REFRESH_READ_LOCK)
|
||||
{
|
||||
/* Check table-level privileges. */
|
||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
if (flush_tables_with_read_lock(thd, all_tables))
|
||||
goto error;
|
||||
my_ok(thd);
|
||||
@ -6511,258 +6382,6 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reload/resets privileges and the different caches.
|
||||
|
||||
@param thd Thread handler (can be NULL!)
|
||||
@param options What should be reset/reloaded (tables, privileges, slave...)
|
||||
@param tables Tables to flush (if any)
|
||||
@param write_to_binlog True if we can write to the binlog.
|
||||
|
||||
@note Depending on 'options', it may be very bad to write the
|
||||
query to the binlog (e.g. FLUSH SLAVE); this is a
|
||||
pointer where reload_acl_and_cache() will put 0 if
|
||||
it thinks we really should not write to the binlog.
|
||||
Otherwise it will put 1.
|
||||
|
||||
@return Error status code
|
||||
@retval 0 Ok
|
||||
@retval !=0 Error; thd->killed is set or thd->is_error() is true
|
||||
*/
|
||||
|
||||
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
bool *write_to_binlog)
|
||||
{
|
||||
bool result=0;
|
||||
select_errors=0; /* Write if more errors */
|
||||
bool tmp_write_to_binlog= 1;
|
||||
|
||||
DBUG_ASSERT(!thd || !thd->in_sub_stmt);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (options & REFRESH_GRANT)
|
||||
{
|
||||
THD *tmp_thd= 0;
|
||||
/*
|
||||
If reload_acl_and_cache() is called from SIGHUP handler we have to
|
||||
allocate temporary THD for execution of acl_reload()/grant_reload().
|
||||
*/
|
||||
if (!thd && (thd= (tmp_thd= new THD)))
|
||||
{
|
||||
thd->thread_stack= (char*) &tmp_thd;
|
||||
thd->store_globals();
|
||||
}
|
||||
|
||||
if (thd)
|
||||
{
|
||||
bool reload_acl_failed= acl_reload(thd);
|
||||
bool reload_grants_failed= grant_reload(thd);
|
||||
bool reload_servers_failed= servers_reload(thd);
|
||||
|
||||
if (reload_acl_failed || reload_grants_failed || reload_servers_failed)
|
||||
{
|
||||
result= 1;
|
||||
/*
|
||||
When an error is returned, my_message may have not been called and
|
||||
the client will hang waiting for a response.
|
||||
*/
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_thd)
|
||||
{
|
||||
delete tmp_thd;
|
||||
/* Remember that we don't have a THD */
|
||||
my_pthread_setspecific_ptr(THR_THD, 0);
|
||||
thd= 0;
|
||||
}
|
||||
reset_mqh((LEX_USER *)NULL, TRUE);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_LOG)
|
||||
{
|
||||
/*
|
||||
Flush the normal query log, the update log, the binary log,
|
||||
the slow query log, the relay log (if it exists) and the log
|
||||
tables.
|
||||
*/
|
||||
|
||||
options|= REFRESH_BINARY_LOG;
|
||||
options|= REFRESH_RELAY_LOG;
|
||||
options|= REFRESH_SLOW_LOG;
|
||||
options|= REFRESH_GENERAL_LOG;
|
||||
options|= REFRESH_ENGINE_LOG;
|
||||
options|= REFRESH_ERROR_LOG;
|
||||
}
|
||||
|
||||
if (options & REFRESH_ERROR_LOG)
|
||||
if (flush_error_log())
|
||||
result= 1;
|
||||
|
||||
if ((options & REFRESH_SLOW_LOG) && opt_slow_log)
|
||||
logger.flush_slow_log();
|
||||
|
||||
if ((options & REFRESH_GENERAL_LOG) && opt_log)
|
||||
logger.flush_general_log();
|
||||
|
||||
if (options & REFRESH_ENGINE_LOG)
|
||||
if (ha_flush_logs(NULL))
|
||||
result= 1;
|
||||
|
||||
if (options & REFRESH_BINARY_LOG)
|
||||
{
|
||||
/*
|
||||
Writing this command to the binlog may result in infinite loops
|
||||
when doing mysqlbinlog|mysql, and anyway it does not really make
|
||||
sense to log it automatically (would cause more trouble to users
|
||||
than it would help them)
|
||||
*/
|
||||
tmp_write_to_binlog= 0;
|
||||
if (mysql_bin_log.is_open())
|
||||
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
|
||||
}
|
||||
if (options & REFRESH_RELAY_LOG)
|
||||
{
|
||||
#ifdef HAVE_REPLICATION
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
rotate_relay_log(active_mi);
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
if (options & REFRESH_QUERY_CACHE_FREE)
|
||||
{
|
||||
query_cache.pack(); // FLUSH QUERY CACHE
|
||||
options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
|
||||
}
|
||||
if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
|
||||
{
|
||||
query_cache.flush(); // RESET QUERY CACHE
|
||||
}
|
||||
#endif /*HAVE_QUERY_CACHE*/
|
||||
|
||||
DBUG_ASSERT(!thd || thd->locked_tables_mode ||
|
||||
!thd->mdl_context.has_locks() ||
|
||||
thd->handler_tables_hash.records ||
|
||||
thd->global_read_lock.is_acquired());
|
||||
|
||||
/*
|
||||
Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
|
||||
(see sql_yacc.yy)
|
||||
*/
|
||||
if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
|
||||
{
|
||||
if ((options & REFRESH_READ_LOCK) && thd)
|
||||
{
|
||||
/*
|
||||
On the first hand we need write lock on the tables to be flushed,
|
||||
on the other hand we must not try to aspire a global read lock
|
||||
if we have a write locked table as this would lead to a deadlock
|
||||
when trying to reopen (and re-lock) the table after the flush.
|
||||
*/
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
Writing to the binlog could cause deadlocks, as we don't log
|
||||
UNLOCK TABLES
|
||||
*/
|
||||
tmp_write_to_binlog= 0;
|
||||
if (thd->global_read_lock.lock_global_read_lock(thd))
|
||||
return 1; // Killed
|
||||
if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
|
||||
FALSE : TRUE))
|
||||
result= 1;
|
||||
|
||||
if (thd->global_read_lock.make_global_read_lock_block_commit(thd)) // Killed
|
||||
{
|
||||
/* Don't leave things in a half-locked state */
|
||||
thd->global_read_lock.unlock_global_read_lock(thd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd && thd->locked_tables_mode)
|
||||
{
|
||||
/*
|
||||
If we are under LOCK TABLES we should have a write
|
||||
lock on tables which we are going to flush.
|
||||
*/
|
||||
if (tables)
|
||||
{
|
||||
for (TABLE_LIST *t= tables; t; t= t->next_local)
|
||||
if (!find_table_for_mdl_upgrade(thd->open_tables, t->db,
|
||||
t->table_name, FALSE))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TABLE *tab= thd->open_tables; tab; tab= tab->next)
|
||||
{
|
||||
if (! tab->mdl_ticket->is_upgradable_or_exclusive())
|
||||
{
|
||||
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
|
||||
tab->s->table_name.str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
|
||||
FALSE : TRUE))
|
||||
result= 1;
|
||||
}
|
||||
my_dbopt_cleanup();
|
||||
}
|
||||
if (options & REFRESH_HOSTS)
|
||||
hostname_cache_refresh();
|
||||
if (thd && (options & REFRESH_STATUS))
|
||||
refresh_status(thd);
|
||||
if (options & REFRESH_THREADS)
|
||||
flush_thread_cache();
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (options & REFRESH_MASTER)
|
||||
{
|
||||
DBUG_ASSERT(thd);
|
||||
tmp_write_to_binlog= 0;
|
||||
if (reset_master(thd))
|
||||
{
|
||||
result=1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef OPENSSL
|
||||
if (options & REFRESH_DES_KEY_FILE)
|
||||
{
|
||||
if (des_key_file && load_des_key_file(des_key_file))
|
||||
result= 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (options & REFRESH_SLAVE)
|
||||
{
|
||||
tmp_write_to_binlog= 0;
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
if (reset_slave(thd, active_mi))
|
||||
result=1;
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_USER_RESOURCES)
|
||||
reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
|
||||
*write_to_binlog= tmp_write_to_binlog;
|
||||
/*
|
||||
If the query was killed then this function must fail.
|
||||
*/
|
||||
return result || (thd ? thd->killed : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
kill on thread.
|
||||
|
||||
|
@ -93,8 +93,6 @@ void mysql_init_multi_delete(LEX *lex);
|
||||
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
|
||||
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
||||
pthread_handler_t handle_bootstrap(void *arg);
|
||||
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
bool *write_to_binlog);
|
||||
int mysql_execute_command(THD *thd);
|
||||
bool do_command(THD *thd);
|
||||
void do_handle_bootstrap(THD *thd);
|
||||
|
@ -6342,7 +6342,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
*/
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||
table->s->db.str,
|
||||
table->s->table_name.str);
|
||||
table->s->table_name.str, TRUE);
|
||||
}
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
@ -1393,8 +1393,9 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
|
||||
READ_RECORD read_record_info;
|
||||
int error;
|
||||
THD *new_thd= &thd;
|
||||
bool result;
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
bool table_exists;
|
||||
No_such_table_error_handler error_handler;
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
DBUG_ENTER("plugin_load");
|
||||
|
||||
@ -1410,13 +1411,18 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
|
||||
When building an embedded library, if the mysql.plugin table
|
||||
does not exist, we silently ignore the missing table
|
||||
*/
|
||||
if (check_if_table_exists(new_thd, &tables, &table_exists))
|
||||
table_exists= FALSE;
|
||||
if (!table_exists)
|
||||
new_thd->push_internal_handler(&error_handler);
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
|
||||
result= open_and_lock_tables(new_thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT);
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
new_thd->pop_internal_handler();
|
||||
if (error_handler.safely_trapped_errors())
|
||||
goto end;
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
|
||||
if (open_and_lock_tables(new_thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
|
||||
if (result)
|
||||
{
|
||||
DBUG_PRINT("error",("Can't open plugin table"));
|
||||
sql_print_error("Can't open the mysql.plugin table. Please "
|
||||
|
427
sql/sql_reload.cc
Normal file
427
sql/sql_reload.cc
Normal file
@ -0,0 +1,427 @@
|
||||
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "sql_reload.h"
|
||||
#include "sql_priv.h"
|
||||
#include "mysqld.h" // select_errors
|
||||
#include "sql_class.h" // THD
|
||||
#include "sql_acl.h" // acl_reload
|
||||
#include "sql_servers.h" // servers_reload
|
||||
#include "sql_connect.h" // reset_mqh
|
||||
#include "sql_base.h" // close_cached_tables
|
||||
#include "sql_db.h" // my_dbopt_cleanup
|
||||
#include "hostname.h" // hostname_cache_refresh
|
||||
#include "sql_repl.h" // reset_master, reset_slave
|
||||
#include "debug_sync.h"
|
||||
|
||||
|
||||
/**
|
||||
Reload/resets privileges and the different caches.
|
||||
|
||||
@param thd Thread handler (can be NULL!)
|
||||
@param options What should be reset/reloaded (tables, privileges, slave...)
|
||||
@param tables Tables to flush (if any)
|
||||
@param write_to_binlog True if we can write to the binlog.
|
||||
|
||||
@note Depending on 'options', it may be very bad to write the
|
||||
query to the binlog (e.g. FLUSH SLAVE); this is a
|
||||
pointer where reload_acl_and_cache() will put 0 if
|
||||
it thinks we really should not write to the binlog.
|
||||
Otherwise it will put 1.
|
||||
|
||||
@return Error status code
|
||||
@retval 0 Ok
|
||||
@retval !=0 Error; thd->killed is set or thd->is_error() is true
|
||||
*/
|
||||
|
||||
bool reload_acl_and_cache(THD *thd, unsigned long options,
|
||||
TABLE_LIST *tables, bool *write_to_binlog)
|
||||
{
|
||||
bool result=0;
|
||||
select_errors=0; /* Write if more errors */
|
||||
bool tmp_write_to_binlog= 1;
|
||||
|
||||
DBUG_ASSERT(!thd || !thd->in_sub_stmt);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (options & REFRESH_GRANT)
|
||||
{
|
||||
THD *tmp_thd= 0;
|
||||
/*
|
||||
If reload_acl_and_cache() is called from SIGHUP handler we have to
|
||||
allocate temporary THD for execution of acl_reload()/grant_reload().
|
||||
*/
|
||||
if (!thd && (thd= (tmp_thd= new THD)))
|
||||
{
|
||||
thd->thread_stack= (char*) &tmp_thd;
|
||||
thd->store_globals();
|
||||
}
|
||||
|
||||
if (thd)
|
||||
{
|
||||
bool reload_acl_failed= acl_reload(thd);
|
||||
bool reload_grants_failed= grant_reload(thd);
|
||||
bool reload_servers_failed= servers_reload(thd);
|
||||
|
||||
if (reload_acl_failed || reload_grants_failed || reload_servers_failed)
|
||||
{
|
||||
result= 1;
|
||||
/*
|
||||
When an error is returned, my_message may have not been called and
|
||||
the client will hang waiting for a response.
|
||||
*/
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_thd)
|
||||
{
|
||||
delete tmp_thd;
|
||||
/* Remember that we don't have a THD */
|
||||
my_pthread_setspecific_ptr(THR_THD, 0);
|
||||
thd= 0;
|
||||
}
|
||||
reset_mqh((LEX_USER *)NULL, TRUE);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_LOG)
|
||||
{
|
||||
/*
|
||||
Flush the normal query log, the update log, the binary log,
|
||||
the slow query log, the relay log (if it exists) and the log
|
||||
tables.
|
||||
*/
|
||||
|
||||
options|= REFRESH_BINARY_LOG;
|
||||
options|= REFRESH_RELAY_LOG;
|
||||
options|= REFRESH_SLOW_LOG;
|
||||
options|= REFRESH_GENERAL_LOG;
|
||||
options|= REFRESH_ENGINE_LOG;
|
||||
options|= REFRESH_ERROR_LOG;
|
||||
}
|
||||
|
||||
if (options & REFRESH_ERROR_LOG)
|
||||
if (flush_error_log())
|
||||
result= 1;
|
||||
|
||||
if ((options & REFRESH_SLOW_LOG) && opt_slow_log)
|
||||
logger.flush_slow_log();
|
||||
|
||||
if ((options & REFRESH_GENERAL_LOG) && opt_log)
|
||||
logger.flush_general_log();
|
||||
|
||||
if (options & REFRESH_ENGINE_LOG)
|
||||
if (ha_flush_logs(NULL))
|
||||
result= 1;
|
||||
|
||||
if (options & REFRESH_BINARY_LOG)
|
||||
{
|
||||
/*
|
||||
Writing this command to the binlog may result in infinite loops
|
||||
when doing mysqlbinlog|mysql, and anyway it does not really make
|
||||
sense to log it automatically (would cause more trouble to users
|
||||
than it would help them)
|
||||
*/
|
||||
tmp_write_to_binlog= 0;
|
||||
if (mysql_bin_log.is_open())
|
||||
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
|
||||
}
|
||||
if (options & REFRESH_RELAY_LOG)
|
||||
{
|
||||
#ifdef HAVE_REPLICATION
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
rotate_relay_log(active_mi);
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
if (options & REFRESH_QUERY_CACHE_FREE)
|
||||
{
|
||||
query_cache.pack(); // FLUSH QUERY CACHE
|
||||
options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
|
||||
}
|
||||
if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
|
||||
{
|
||||
query_cache.flush(); // RESET QUERY CACHE
|
||||
}
|
||||
#endif /*HAVE_QUERY_CACHE*/
|
||||
|
||||
DBUG_ASSERT(!thd || thd->locked_tables_mode ||
|
||||
!thd->mdl_context.has_locks() ||
|
||||
thd->handler_tables_hash.records ||
|
||||
thd->global_read_lock.is_acquired());
|
||||
|
||||
/*
|
||||
Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
|
||||
(see sql_yacc.yy)
|
||||
*/
|
||||
if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
|
||||
{
|
||||
if ((options & REFRESH_READ_LOCK) && thd)
|
||||
{
|
||||
/*
|
||||
On the first hand we need write lock on the tables to be flushed,
|
||||
on the other hand we must not try to aspire a global read lock
|
||||
if we have a write locked table as this would lead to a deadlock
|
||||
when trying to reopen (and re-lock) the table after the flush.
|
||||
*/
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
Writing to the binlog could cause deadlocks, as we don't log
|
||||
UNLOCK TABLES
|
||||
*/
|
||||
tmp_write_to_binlog= 0;
|
||||
if (thd->global_read_lock.lock_global_read_lock(thd))
|
||||
return 1; // Killed
|
||||
if (close_cached_tables(thd, tables,
|
||||
((options & REFRESH_FAST) ? FALSE : TRUE),
|
||||
thd->variables.lock_wait_timeout))
|
||||
result= 1;
|
||||
|
||||
if (thd->global_read_lock.make_global_read_lock_block_commit(thd)) // Killed
|
||||
{
|
||||
/* Don't leave things in a half-locked state */
|
||||
thd->global_read_lock.unlock_global_read_lock(thd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd && thd->locked_tables_mode)
|
||||
{
|
||||
/*
|
||||
If we are under LOCK TABLES we should have a write
|
||||
lock on tables which we are going to flush.
|
||||
*/
|
||||
if (tables)
|
||||
{
|
||||
for (TABLE_LIST *t= tables; t; t= t->next_local)
|
||||
if (!find_table_for_mdl_upgrade(thd->open_tables, t->db,
|
||||
t->table_name, FALSE))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TABLE *tab= thd->open_tables; tab; tab= tab->next)
|
||||
{
|
||||
if (! tab->mdl_ticket->is_upgradable_or_exclusive())
|
||||
{
|
||||
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
|
||||
tab->s->table_name.str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (close_cached_tables(thd, tables,
|
||||
((options & REFRESH_FAST) ? FALSE : TRUE),
|
||||
(thd ? thd->variables.lock_wait_timeout :
|
||||
LONG_TIMEOUT)))
|
||||
result= 1;
|
||||
}
|
||||
my_dbopt_cleanup();
|
||||
}
|
||||
if (options & REFRESH_HOSTS)
|
||||
hostname_cache_refresh();
|
||||
if (thd && (options & REFRESH_STATUS))
|
||||
refresh_status(thd);
|
||||
if (options & REFRESH_THREADS)
|
||||
flush_thread_cache();
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (options & REFRESH_MASTER)
|
||||
{
|
||||
DBUG_ASSERT(thd);
|
||||
tmp_write_to_binlog= 0;
|
||||
if (reset_master(thd))
|
||||
{
|
||||
result=1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef OPENSSL
|
||||
if (options & REFRESH_DES_KEY_FILE)
|
||||
{
|
||||
if (des_key_file && load_des_key_file(des_key_file))
|
||||
result= 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (options & REFRESH_SLAVE)
|
||||
{
|
||||
tmp_write_to_binlog= 0;
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
if (reset_slave(thd, active_mi))
|
||||
result=1;
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_USER_RESOURCES)
|
||||
reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
|
||||
*write_to_binlog= tmp_write_to_binlog;
|
||||
/*
|
||||
If the query was killed then this function must fail.
|
||||
*/
|
||||
return result || (thd ? thd->killed : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Implementation of FLUSH TABLES <table_list> WITH READ LOCK.
|
||||
|
||||
In brief: take exclusive locks, expel tables from the table
|
||||
cache, reopen the tables, enter the 'LOCKED TABLES' mode,
|
||||
downgrade the locks.
|
||||
Note: the function is written to be called from
|
||||
mysql_execute_command(), it is not reusable in arbitrary
|
||||
execution context.
|
||||
|
||||
Required privileges
|
||||
-------------------
|
||||
Since the statement implicitly enters LOCK TABLES mode,
|
||||
it requires LOCK TABLES privilege on every table.
|
||||
But since the rest of FLUSH commands require
|
||||
the global RELOAD_ACL, it also requires RELOAD_ACL.
|
||||
|
||||
Compatibility with the global read lock
|
||||
---------------------------------------
|
||||
We don't wait for the GRL, since neither the
|
||||
5.1 combination that this new statement is intended to
|
||||
replace (LOCK TABLE <list> WRITE; FLUSH TABLES;),
|
||||
nor FLUSH TABLES WITH READ LOCK do.
|
||||
@todo: this is not implemented, Dmitry disagrees.
|
||||
Currently we wait for GRL in another connection,
|
||||
but are compatible with a GRL in our own connection.
|
||||
|
||||
Behaviour under LOCK TABLES
|
||||
---------------------------
|
||||
Bail out: i.e. don't perform an implicit UNLOCK TABLES.
|
||||
This is not consistent with LOCK TABLES statement, but is
|
||||
in line with behaviour of FLUSH TABLES WITH READ LOCK, and we
|
||||
try to not introduce any new statements with implicit
|
||||
semantics.
|
||||
|
||||
Compatibility with parallel updates
|
||||
-----------------------------------
|
||||
As a result, we will wait for all open transactions
|
||||
against the tables to complete. After the lock downgrade,
|
||||
new transactions will be able to read the tables, but not
|
||||
write to them.
|
||||
|
||||
Differences from FLUSH TABLES <list>
|
||||
-------------------------------------
|
||||
- you can't flush WITH READ LOCK a non-existent table
|
||||
- you can't flush WITH READ LOCK under LOCK TABLES
|
||||
- currently incompatible with the GRL (@todo: fix)
|
||||
|
||||
Effect on views and temporary tables.
|
||||
------------------------------------
|
||||
You can only apply this command to existing base tables.
|
||||
If a view with such name exists, ER_WRONG_OBJECT is returned.
|
||||
If a temporary table with such name exists, it's ignored:
|
||||
if there is a base table, it's used, otherwise ER_NO_SUCH_TABLE
|
||||
is returned.
|
||||
|
||||
Implicit commit
|
||||
---------------
|
||||
This statement causes an implicit commit before and
|
||||
after it.
|
||||
|
||||
HANDLER SQL
|
||||
-----------
|
||||
If this connection has HANDLERs open against
|
||||
some of the tables being FLUSHed, these handlers
|
||||
are implicitly flushed (lose their position).
|
||||
*/
|
||||
|
||||
bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
||||
{
|
||||
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
|
||||
TABLE_LIST *table_list;
|
||||
MDL_request_list mdl_requests;
|
||||
|
||||
/*
|
||||
This is called from SQLCOM_FLUSH, the transaction has
|
||||
been committed implicitly.
|
||||
*/
|
||||
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
Acquire SNW locks on tables to be flushed. We can't use
|
||||
lock_table_names() here as this call will also acquire global IX
|
||||
and database-scope IX locks on the tables, and this will make
|
||||
this statement incompatible with FLUSH TABLES WITH READ LOCK.
|
||||
*/
|
||||
for (table_list= all_tables; table_list;
|
||||
table_list= table_list->next_global)
|
||||
mdl_requests.push_front(&table_list->mdl_request);
|
||||
|
||||
if (thd->mdl_context.acquire_locks(&mdl_requests,
|
||||
thd->variables.lock_wait_timeout))
|
||||
goto error;
|
||||
|
||||
DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks");
|
||||
|
||||
for (table_list= all_tables; table_list;
|
||||
table_list= table_list->next_global)
|
||||
{
|
||||
/* Request removal of table from cache. */
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||
table_list->db,
|
||||
table_list->table_name, FALSE);
|
||||
|
||||
/* Skip views and temporary tables. */
|
||||
table_list->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
|
||||
table_list->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
|
||||
}
|
||||
|
||||
/*
|
||||
Before opening and locking tables the below call also waits
|
||||
for old shares to go away, so the fact that we don't pass
|
||||
MYSQL_LOCK_IGNORE_FLUSH flag to it is important.
|
||||
*/
|
||||
if (open_and_lock_tables(thd, all_tables, FALSE,
|
||||
MYSQL_OPEN_HAS_MDL_LOCK,
|
||||
&lock_tables_prelocking_strategy) ||
|
||||
thd->locked_tables_list.init_locked_tables(thd))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
thd->variables.option_bits|= OPTION_TABLE_LOCK;
|
||||
|
||||
/*
|
||||
We don't downgrade MDL_SHARED_NO_WRITE here as the intended
|
||||
post effect of this call is identical to LOCK TABLES <...> READ,
|
||||
and we didn't use thd->in_lock_talbes and
|
||||
thd->sql_command= SQLCOM_LOCK_TABLES hacks to enter the LTM.
|
||||
*/
|
||||
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
26
sql/sql_reload.h
Normal file
26
sql/sql_reload.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef SQL_RELOAD_INCLUDED
|
||||
#define SQL_RELOAD_INCLUDED
|
||||
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
class THD;
|
||||
struct TABLE_LIST;
|
||||
|
||||
bool reload_acl_and_cache(THD *thd, unsigned long options,
|
||||
TABLE_LIST *tables, bool *write_to_binlog);
|
||||
|
||||
bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables);
|
||||
|
||||
#endif
|
@ -147,13 +147,15 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
MYSQL_OPEN_SKIP_TEMPORARY))
|
||||
goto err;
|
||||
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
|
||||
for (ren_table= table_list; ren_table; ren_table= ren_table->next_local)
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, ren_table->db,
|
||||
ren_table->table_name);
|
||||
ren_table->table_name, FALSE);
|
||||
|
||||
error=0;
|
||||
/*
|
||||
An exclusive lock on table names is satisfactory to ensure
|
||||
no other thread accesses this table.
|
||||
*/
|
||||
if ((ren_table=rename_tables(thd,table_list,0)))
|
||||
{
|
||||
/* Rename didn't succeed; rename back the tables in reverse order */
|
||||
@ -175,17 +177,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
|
||||
error= 1;
|
||||
}
|
||||
/*
|
||||
An exclusive lock on table names is satisfactory to ensure
|
||||
no other thread accesses this table.
|
||||
However, NDB assumes that handler::rename_tables is called under
|
||||
LOCK_open. And it indeed is, from ALTER TABLE.
|
||||
TODO: remove this limitation.
|
||||
We still should unlock LOCK_open as early as possible, to provide
|
||||
higher concurrency - query_cache_invalidate can take minutes to
|
||||
complete.
|
||||
*/
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
if (!silent && !error)
|
||||
{
|
||||
@ -197,8 +188,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
if (!error)
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
|
||||
err:
|
||||
thd->global_read_lock.start_waiting_global_read_lock(thd);
|
||||
DBUG_RETURN(error || binlog_error);
|
||||
|
@ -628,7 +628,7 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
|
||||
/* close the servers table before we call closed_cached_connection_tables */
|
||||
close_mysql_tables(thd);
|
||||
|
||||
if (close_cached_connection_tables(thd, TRUE, &name))
|
||||
if (close_cached_connection_tables(thd, &name))
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_UNKNOWN_ERROR, "Server connection in use");
|
||||
@ -1057,7 +1057,7 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
|
||||
/* close the servers table before we call closed_cached_connection_tables */
|
||||
close_mysql_tables(thd);
|
||||
|
||||
if (close_cached_connection_tables(thd, FALSE, &name))
|
||||
if (close_cached_connection_tables(thd, &name))
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_UNKNOWN_ERROR, "Server connection in use");
|
||||
|
@ -3273,8 +3273,8 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
/*
|
||||
TODO: investigate if in this particular situation we can get by
|
||||
simply obtaining internal lock of data-dictionary (ATM it
|
||||
is LOCK_open) instead of obtaning full-blown metadata lock.
|
||||
simply obtaining internal lock of the data-dictionary
|
||||
instead of obtaining full-blown metadata lock.
|
||||
*/
|
||||
if (try_acquire_high_prio_shared_mdl_lock(thd, &table_list, can_deadlock))
|
||||
{
|
||||
@ -7657,7 +7657,7 @@ static bool show_create_trigger_impl(THD *thd,
|
||||
*/
|
||||
|
||||
static
|
||||
TABLE_LIST *get_trigger_table_impl(THD *thd, const sp_name *trg_name)
|
||||
TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
|
||||
{
|
||||
char trn_path_buff[FN_REFLEN];
|
||||
LEX_STRING trn_path= { trn_path_buff, 0 };
|
||||
@ -7694,39 +7694,6 @@ TABLE_LIST *get_trigger_table_impl(THD *thd, const sp_name *trg_name)
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
Read TRN and TRG files to obtain base table name for the specified
|
||||
trigger name and construct TABE_LIST object for the base table. Acquire
|
||||
LOCK_open when doing this.
|
||||
|
||||
@param thd Thread context.
|
||||
@param trg_name Trigger name.
|
||||
|
||||
@return TABLE_LIST object corresponding to the base table.
|
||||
*/
|
||||
|
||||
static
|
||||
TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
|
||||
{
|
||||
/* Acquire LOCK_open (stop the server). */
|
||||
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
|
||||
/*
|
||||
Load base table name from the TRN-file and create TABLE_LIST object.
|
||||
*/
|
||||
|
||||
TABLE_LIST *lst= get_trigger_table_impl(thd, trg_name);
|
||||
|
||||
/* Release LOCK_open (continue the server). */
|
||||
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
/* That's it. */
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
SHOW CREATE TRIGGER high-level implementation.
|
||||
|
@ -1719,7 +1719,6 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
|
||||
completing this we write a new phase to the log entry that will
|
||||
deactivate it.
|
||||
*/
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)) ||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
lpt->table->file->ha_create_handler_files(path, shadow_path,
|
||||
@ -1775,12 +1774,12 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
|
||||
#endif
|
||||
|
||||
err:
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
|
||||
part_info->frm_log_entry= NULL;
|
||||
(void) sync_ddl_log();
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
end:
|
||||
@ -1999,10 +1998,11 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout,
|
||||
MYSQL_OPEN_SKIP_TEMPORARY))
|
||||
DBUG_RETURN(1);
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
for (table= tables; table; table= table->next_local)
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name);
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
{
|
||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2171,15 +2171,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
built_query.append("`,");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Investigate what should be done to remove this lock completely.
|
||||
Is exclusive meta-data lock enough ?
|
||||
*/
|
||||
DEBUG_SYNC(thd, "rm_table_part2_before_delete_table");
|
||||
DBUG_EXECUTE_IF("sleep_before_part2_delete_table",
|
||||
my_sleep(100000););
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
error= 0;
|
||||
if (drop_temporary ||
|
||||
((access(path, F_OK) &&
|
||||
@ -2209,8 +2203,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
char *end;
|
||||
/*
|
||||
Cannot use the db_type from the table, since that might have changed
|
||||
while waiting for the exclusive name lock. We are under LOCK_open,
|
||||
so reading from the frm-file is safe.
|
||||
while waiting for the exclusive name lock.
|
||||
*/
|
||||
if (frm_db_type == DB_TYPE_UNKNOWN)
|
||||
{
|
||||
@ -2252,7 +2245,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
}
|
||||
non_tmp_error= error ? TRUE : non_tmp_error;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
if (error)
|
||||
{
|
||||
if (wrong_tables.length())
|
||||
@ -4098,7 +4090,6 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
goto err;
|
||||
}
|
||||
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||
{
|
||||
if (!access(path,F_OK))
|
||||
@ -4106,7 +4097,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
||||
goto warn;
|
||||
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
We don't assert here, but check the result, because the table could be
|
||||
@ -4116,11 +4107,14 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
Then she could create the table. This case is pretty obscure and
|
||||
therefore we don't introduce a new error message only for it.
|
||||
*/
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (get_cached_table_share(db, table_name))
|
||||
{
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4128,7 +4122,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
exist in any storage engine. In such a case it should
|
||||
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
|
||||
unless user specified CREATE TABLE IF EXISTS
|
||||
The LOCK_open mutex has been locked to make sure no
|
||||
An exclusive metadata lock ensures that no
|
||||
one else is attempting to discover the table. Since
|
||||
it's not on disk as a frm file, no one could be using it!
|
||||
*/
|
||||
@ -4149,12 +4143,12 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (create_if_not_exists)
|
||||
goto warn;
|
||||
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
|
||||
my_error(retcode, MYF(0),table_name);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4186,7 +4180,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (test_if_data_home_dir(dirpath))
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (create_info->index_file_name)
|
||||
@ -4195,7 +4189,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (test_if_data_home_dir(dirpath))
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4203,7 +4197,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (check_partition_dirs(thd->lex->part_info))
|
||||
{
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
||||
|
||||
@ -4226,7 +4220,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (rea_create_table(thd, path, db, table_name,
|
||||
create_info, alter_info->create_list,
|
||||
key_count, key_info_buffer, file))
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
|
||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||
{
|
||||
@ -4235,7 +4229,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
if (!(table= open_temporary_table(thd, path, db, table_name, 1)))
|
||||
{
|
||||
(void) rm_temporary_table(create_info->db_type, path);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (is_trans != NULL)
|
||||
@ -4245,9 +4239,6 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
}
|
||||
|
||||
error= FALSE;
|
||||
unlock_and_end:
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
err:
|
||||
thd_proc_info(thd, "After create");
|
||||
delete file;
|
||||
@ -4258,7 +4249,7 @@ warn:
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
|
||||
alias);
|
||||
goto unlock_and_end;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
@ -5920,7 +5911,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
else
|
||||
{
|
||||
*fn_ext(new_name)=0;
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
|
||||
error= -1;
|
||||
else if (Table_triggers_list::change_table_name(thd, db, table_name,
|
||||
@ -5930,7 +5920,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
table_name, 0);
|
||||
error= -1;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6549,7 +6538,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
/* This type cannot happen in regular ALTER. */
|
||||
new_db_type= old_db_type= NULL;
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
|
||||
FN_TO_IS_TMP))
|
||||
{
|
||||
@ -6576,8 +6564,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
if (! error)
|
||||
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
||||
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
if (error)
|
||||
{
|
||||
/* This shouldn't happen. But let us play it safe. */
|
||||
@ -7192,4 +7178,3 @@ static bool check_engine(THD *thd, const char *table_name,
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ static void print_cached_tables(void)
|
||||
printf("unused_links isn't linked properly\n");
|
||||
return;
|
||||
}
|
||||
} while (count++ < table_cache_count && (lnk=lnk->next) != start_link);
|
||||
} while (count++ < cached_open_tables() && (lnk=lnk->next) != start_link);
|
||||
if (lnk != start_link)
|
||||
{
|
||||
printf("Unused_links aren't connected\n");
|
||||
@ -416,7 +416,7 @@ static void display_table_locks(void)
|
||||
void *saved_base;
|
||||
DYNAMIC_ARRAY saved_table_locks;
|
||||
|
||||
(void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO), table_cache_count + 20,50);
|
||||
(void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO), cached_open_tables() + 20,50);
|
||||
mysql_mutex_lock(&THR_LOCK_lock);
|
||||
for (list= thr_lock_thread_list; list; list= list_rest(list))
|
||||
{
|
||||
|
@ -394,9 +394,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
/*
|
||||
We don't want perform our operations while global read lock is held
|
||||
so we have to wait until its end and then prevent it from occurring
|
||||
again until we are done, unless we are under lock tables. (Acquiring
|
||||
LOCK_open is not enough because global read lock is held without holding
|
||||
LOCK_open).
|
||||
again until we are done, unless we are under lock tables.
|
||||
*/
|
||||
if (!thd->locked_tables_mode &&
|
||||
thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
|
||||
@ -516,11 +514,9 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
goto end;
|
||||
}
|
||||
|
||||
mysql_mutex_lock(&LOCK_open);
|
||||
result= (create ?
|
||||
table->triggers->create_trigger(thd, tables, &stmt_query):
|
||||
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
if (result)
|
||||
goto end;
|
||||
@ -1680,9 +1676,6 @@ bool add_table_for_trigger(THD *thd,
|
||||
@param db schema for table
|
||||
@param name name for table
|
||||
|
||||
@note
|
||||
The calling thread should hold the LOCK_open mutex;
|
||||
|
||||
@retval
|
||||
False success
|
||||
@retval
|
||||
@ -1912,14 +1905,10 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
||||
|
||||
/*
|
||||
This method interfaces the mysql server code protected by
|
||||
either LOCK_open mutex or with an exclusive metadata lock.
|
||||
In the future, only an exclusive metadata lock will be enough.
|
||||
an exclusive metadata lock.
|
||||
*/
|
||||
#ifndef DBUG_OFF
|
||||
if (thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, old_table,
|
||||
MDL_EXCLUSIVE))
|
||||
mysql_mutex_assert_owner(&LOCK_open);
|
||||
#endif
|
||||
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, old_table,
|
||||
MDL_EXCLUSIVE));
|
||||
|
||||
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
||||
my_strcasecmp(table_alias_charset, old_table, new_table));
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user