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_db.Po
|
||||||
libmysqld/.deps/sql_delete.Po
|
libmysqld/.deps/sql_delete.Po
|
||||||
libmysqld/.deps/sql_truncate.Po
|
libmysqld/.deps/sql_truncate.Po
|
||||||
|
libmysqld/.deps/sql_reload.Po
|
||||||
libmysqld/.deps/datadict.Po
|
libmysqld/.deps/datadict.Po
|
||||||
libmysqld/.deps/sql_derived.Po
|
libmysqld/.deps/sql_derived.Po
|
||||||
libmysqld/.deps/sql_do.Po
|
libmysqld/.deps/sql_do.Po
|
||||||
@ -1175,6 +1176,7 @@ libmysqld/sql_cursor.h
|
|||||||
libmysqld/sql_db.cc
|
libmysqld/sql_db.cc
|
||||||
libmysqld/sql_delete.cc
|
libmysqld/sql_delete.cc
|
||||||
libmysqld/sql_truncate.cc
|
libmysqld/sql_truncate.cc
|
||||||
|
libmysqld/sql_reload.cc
|
||||||
libmysqld/datadict.cc
|
libmysqld/datadict.cc
|
||||||
libmysqld/sql_derived.cc
|
libmysqld/sql_derived.cc
|
||||||
libmysqld/sql_do.cc
|
libmysqld/sql_do.cc
|
||||||
@ -2067,6 +2069,7 @@ sql/.deps/sql_cursor.Po
|
|||||||
sql/.deps/sql_db.Po
|
sql/.deps/sql_db.Po
|
||||||
sql/.deps/sql_delete.Po
|
sql/.deps/sql_delete.Po
|
||||||
sql/.deps/sql_truncate.Po
|
sql/.deps/sql_truncate.Po
|
||||||
|
sql/.deps/sql_reload.Po
|
||||||
sql/.deps/datadict.Po
|
sql/.deps/datadict.Po
|
||||||
sql/.deps/sql_derived.Po
|
sql/.deps/sql_derived.Po
|
||||||
sql/.deps/sql_do.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
|
dnl Arguments to this macro is default value for selected plugins
|
||||||
|
|
||||||
AC_DEFUN([_MYSQL_CHECK_PLUGIN_ARGS],[
|
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],[
|
AC_DEFUN([__MYSQL_CHECK_PLUGIN_ARGS],[
|
||||||
|
@ -2606,7 +2606,7 @@ MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
|
|||||||
|
|
||||||
dnl -- ndbcluster requires partition to be enabled
|
dnl -- ndbcluster requires partition to be enabled
|
||||||
|
|
||||||
MYSQL_CONFIGURE_PLUGINS([none])
|
MYSQL_CONFIGURE_PLUGINS([default])
|
||||||
|
|
||||||
# Only build client code?
|
# Only build client code?
|
||||||
AC_ARG_WITH(server,
|
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_trywrlock(A) my_rw_trywrlock((A))
|
||||||
#define rw_unlock(A) my_rw_unlock((A))
|
#define rw_unlock(A) my_rw_unlock((A))
|
||||||
#define rwlock_destroy(A) my_rw_destroy((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 */
|
#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_trywrlock(A) pthread_rwlock_trywrlock(A)
|
||||||
#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
|
#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
|
||||||
#define rw_pr_destroy(A) pthread_rwlock_destroy(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
|
#else
|
||||||
/* Otherwise we have to use our own implementation of read/write locks. */
|
/* Otherwise we have to use our own implementation of read/write locks. */
|
||||||
#define NEED_MY_RW_LOCK 1
|
#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_trywrlock(A) my_rw_trywrlock((A))
|
||||||
#define rw_pr_unlock(A) my_rw_unlock((A))
|
#define rw_pr_unlock(A) my_rw_unlock((A))
|
||||||
#define rw_pr_destroy(A) my_rw_destroy((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) */
|
#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 state; /* -1:writer,0:free,>0:readers */
|
||||||
int waiters; /* number of waiting writers */
|
int waiters; /* number of waiting writers */
|
||||||
my_bool prefer_readers;
|
my_bool prefer_readers;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
pthread_t write_thread;
|
||||||
|
#endif
|
||||||
} my_rw_lock_t;
|
} my_rw_lock_t;
|
||||||
|
|
||||||
extern int my_rw_init(my_rw_lock_t *, my_bool *);
|
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_unlock(my_rw_lock_t *);
|
||||||
extern int my_rw_tryrdlock(my_rw_lock_t *);
|
extern int my_rw_tryrdlock(my_rw_lock_t *);
|
||||||
extern int my_rw_trywrlock(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 */
|
#endif /* NEED_MY_RW_LOCK */
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,6 +215,14 @@ typedef struct st_mysql_cond mysql_cond_t;
|
|||||||
#define mysql_mutex_assert_not_owner(M) \
|
#define mysql_mutex_assert_not_owner(M) \
|
||||||
safe_mutex_assert_not_owner(&(M)->m_mutex)
|
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)
|
@def mysql_mutex_init(K, M, A)
|
||||||
Instrumented mutex_init.
|
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_db.cc ../sql/sql_delete.cc ../sql/sql_derived.cc
|
||||||
../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.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_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_lex.cc ../sql/keycaches.cc
|
||||||
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
|
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
|
||||||
../sql/sql_binlog.cc ../sql/sql_manager.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 \
|
opt_sum.cc procedure.cc records.cc sql_acl.cc \
|
||||||
sql_load.cc discover.cc sql_locale.cc \
|
sql_load.cc discover.cc sql_locale.cc \
|
||||||
sql_profile.cc sql_admin.cc sql_truncate.cc datadict.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_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_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
|
||||||
sql_lex.cc sql_list.cc sql_manager.cc \
|
sql_lex.cc sql_list.cc sql_manager.cc \
|
||||||
|
@ -153,7 +153,7 @@ connection master;
|
|||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||||
WHERE info = "RENAME TABLE t1 TO t3, t2 TO t1" and
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
@ -43,7 +43,8 @@ connection default;
|
|||||||
# of our statement.
|
# of our statement.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--disable_result_log
|
--disable_result_log
|
||||||
|
@ -523,7 +523,7 @@ connection waiter;
|
|||||||
--echo connection: waiter
|
--echo connection: waiter
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Flushing tables";
|
where state = "Waiting for table flush";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
connection default;
|
connection default;
|
||||||
--echo connection: default
|
--echo connection: default
|
||||||
@ -557,7 +557,8 @@ connection waiter;
|
|||||||
--echo connection: waiter
|
--echo connection: waiter
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
connection default;
|
connection default;
|
||||||
--echo connection: default
|
--echo connection: default
|
||||||
@ -743,7 +744,8 @@ send alter table t1 engine=memory;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
connection default;
|
connection default;
|
||||||
--error ER_ILLEGAL_HA
|
--error ER_ILLEGAL_HA
|
||||||
@ -764,7 +766,8 @@ send alter table t1 engine=memory;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
connection default;
|
connection default;
|
||||||
--echo # Since S metadata lock was already acquired at HANDLER OPEN time
|
--echo # Since S metadata lock was already acquired at HANDLER OPEN time
|
||||||
@ -1024,7 +1027,9 @@ connection con1;
|
|||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
connection con2;
|
connection con2;
|
||||||
--echo # Waitng for 'drop table t1' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -1055,7 +1060,9 @@ connection con1;
|
|||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
connection con2;
|
connection con2;
|
||||||
--echo # Waiting for 'drop table t1' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -1097,7 +1104,8 @@ send rename table t0 to t3, t1 to t0, t3 to t1;
|
|||||||
connection con1;
|
connection con1;
|
||||||
--echo # Waiting for 'rename table ...' to get blocked...
|
--echo # Waiting for 'rename table ...' to get blocked...
|
||||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -1137,7 +1145,9 @@ connection con2;
|
|||||||
--echo # --> connection con1
|
--echo # --> connection con1
|
||||||
connection con1;
|
connection con1;
|
||||||
--echo # Waiting for 'drop table t2' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -1146,7 +1156,9 @@ send select * from t2;
|
|||||||
--echo # --> connection con1
|
--echo # --> connection con1
|
||||||
connection con1;
|
connection con1;
|
||||||
--echo # Waiting for 'select * from t2' to get blocked...
|
--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;
|
unlock tables;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
connection con2;
|
connection con2;
|
||||||
@ -1190,10 +1202,14 @@ connection default;
|
|||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
connection con3;
|
connection con3;
|
||||||
--echo # Waiting for 'drop table t1' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # Waiting for 'drop table t2' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
||||||
--echo # after ROLLBACK TO SAVEPOINT
|
--echo # after ROLLBACK TO SAVEPOINT
|
||||||
@ -1255,10 +1271,14 @@ connection default;
|
|||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
connection con3;
|
connection con3;
|
||||||
--echo # Waiting for 'drop table t1' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # Waiting for 'drop table t2' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
--echo # Demonstrate that t2 lock was released and t2 was dropped
|
||||||
--echo # after ROLLBACK TO SAVEPOINT
|
--echo # after ROLLBACK TO SAVEPOINT
|
||||||
@ -1314,7 +1334,9 @@ drop table t1, t2;
|
|||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
connection con2;
|
connection con2;
|
||||||
--echo # Waiting for 'drop table t3' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||||
--echo # lock.
|
--echo # lock.
|
||||||
@ -1348,7 +1370,9 @@ send drop table t2;
|
|||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
connection con2;
|
connection con2;
|
||||||
--echo # Waiting for 'drop table t2' to get blocked...
|
--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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connection con1
|
--echo # --> connection con1
|
||||||
connection con1;
|
connection con1;
|
||||||
@ -1400,7 +1424,8 @@ connection con2;
|
|||||||
--echo # has read from the table commits.
|
--echo # has read from the table commits.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
@ -1427,7 +1452,8 @@ connection con1;
|
|||||||
--echo # Waiting for 'handler t1 read a next' to get blocked...
|
--echo # Waiting for 'handler t1 read a next' to get blocked...
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # The below 'drop table t1' should be able to proceed without
|
--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
|
--echo # Connection default
|
||||||
connection default;
|
connection default;
|
||||||
let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
@ -116,3 +116,22 @@ OK: create event: database does not exist
|
|||||||
delete from t1;
|
delete from t1;
|
||||||
commit work;
|
commit work;
|
||||||
drop database events_test;
|
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);
|
insert into t2 (a) values (3);
|
||||||
# --> connection default;
|
# --> connection default;
|
||||||
unlock tables;
|
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
|
# --> connection con1
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
#
|
#
|
||||||
@ -234,3 +279,97 @@ drop temporary table v1;
|
|||||||
unlock tables;
|
unlock tables;
|
||||||
drop view v2, v3;
|
drop view v2, v3;
|
||||||
drop table t1, v1;
|
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
|
NULL
|
||||||
drop table t2;
|
drop table t2;
|
||||||
set foreign_key_checks = 1;
|
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'.
|
# Switching to connection 'default'.
|
||||||
# Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK.
|
# Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK.
|
||||||
drop table t1;
|
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';
|
set debug_sync= 'RESET';
|
||||||
#
|
#
|
||||||
# Test for bug #46748 "Assertion in MDL_context::wait_for_locks()
|
# 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;
|
set query_cache_wlock_invalidate=1;
|
||||||
create table t1 (a int not null);
|
create table t1 (a int not null);
|
||||||
create table t2 (a int not null);
|
create table t2 (a int not null);
|
||||||
|
create view v1 as select * from t1;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
select * from t2;
|
select * from t2;
|
||||||
@ -713,6 +714,17 @@ show status like "Qcache_queries_in_cache";
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_queries_in_cache 1
|
Qcache_queries_in_cache 1
|
||||||
unlock table;
|
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;
|
drop table t1,t2;
|
||||||
set query_cache_wlock_invalidate=default;
|
set query_cache_wlock_invalidate=default;
|
||||||
CREATE TABLE t1 (id INT PRIMARY KEY);
|
CREATE TABLE t1 (id INT PRIMARY KEY);
|
||||||
@ -853,7 +865,7 @@ Variable_name Value
|
|||||||
Qcache_queries_in_cache 0
|
Qcache_queries_in_cache 0
|
||||||
show status like "Qcache_inserts";
|
show status like "Qcache_inserts";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_inserts 18
|
Qcache_inserts 19
|
||||||
show status like "Qcache_hits";
|
show status like "Qcache_hits";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_hits 6
|
Qcache_hits 6
|
||||||
@ -866,7 +878,7 @@ Variable_name Value
|
|||||||
Qcache_queries_in_cache 1
|
Qcache_queries_in_cache 1
|
||||||
show status like "Qcache_inserts";
|
show status like "Qcache_inserts";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_inserts 19
|
Qcache_inserts 20
|
||||||
show status like "Qcache_hits";
|
show status like "Qcache_hits";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_hits 7
|
Qcache_hits 7
|
||||||
|
@ -16,21 +16,19 @@ drop schema foo;
|
|||||||
# Bug #48940 MDL deadlocks against mysql_rm_db
|
# Bug #48940 MDL deadlocks against mysql_rm_db
|
||||||
#
|
#
|
||||||
DROP SCHEMA IF EXISTS schema1;
|
DROP SCHEMA IF EXISTS schema1;
|
||||||
DROP SCHEMA IF EXISTS schema2;
|
|
||||||
# Connection default
|
# Connection default
|
||||||
CREATE SCHEMA schema1;
|
CREATE SCHEMA schema1;
|
||||||
CREATE SCHEMA schema2;
|
|
||||||
CREATE TABLE schema1.t1 (a INT);
|
CREATE TABLE schema1.t1 (a INT);
|
||||||
SET autocommit= FALSE;
|
SET autocommit= FALSE;
|
||||||
INSERT INTO schema1.t1 VALUES (1);
|
INSERT INTO schema1.t1 VALUES (1);
|
||||||
# Connection 2
|
# Connection 2
|
||||||
DROP SCHEMA schema1;
|
DROP SCHEMA schema1;
|
||||||
# Connection default
|
# 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;
|
SET autocommit= TRUE;
|
||||||
# Connection 2
|
# Connection 2
|
||||||
# Connection default
|
# Connection default
|
||||||
DROP SCHEMA schema2;
|
|
||||||
#
|
#
|
||||||
# Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
|
# Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
|
||||||
#
|
#
|
||||||
|
@ -148,12 +148,12 @@ f1()
|
|||||||
# Sending 'drop procedure p1'...
|
# Sending 'drop procedure p1'...
|
||||||
drop procedure p1;
|
drop procedure p1;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -174,12 +174,12 @@ f1()
|
|||||||
# Sending 'create procedure p1'...
|
# Sending 'create procedure p1'...
|
||||||
create procedure p1() begin end;
|
create procedure p1() begin end;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -200,12 +200,12 @@ f1()
|
|||||||
# Sending 'alter procedure p1'...
|
# Sending 'alter procedure p1'...
|
||||||
alter procedure p1 contains sql;
|
alter procedure p1 contains sql;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -226,12 +226,12 @@ f1()
|
|||||||
# Sending 'drop function f1'...
|
# Sending 'drop function f1'...
|
||||||
drop function f1;
|
drop function f1;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -252,12 +252,12 @@ f1()
|
|||||||
# Sending 'create function f1'...
|
# Sending 'create function f1'...
|
||||||
create function f1() returns int return 2;
|
create function f1() returns int return 2;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -279,12 +279,12 @@ f1()
|
|||||||
# Sending 'alter function f1'...
|
# Sending 'alter function f1'...
|
||||||
alter function f1 contains sql;
|
alter function f1 contains sql;
|
||||||
# --> connection con2
|
# --> 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.
|
# Demonstrate that there is a pending exclusive lock.
|
||||||
# Sending 'select f1()'...
|
# Sending 'select f1()'...
|
||||||
select f1();
|
select f1();
|
||||||
# --> connection con3
|
# --> 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
|
# --> connection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -360,7 +360,7 @@ insert into t1 (a) values (1);
|
|||||||
# Sending 'drop function f1'
|
# Sending 'drop function f1'
|
||||||
drop function f1;
|
drop function f1;
|
||||||
# --> connection con2
|
# --> 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
|
# --> connnection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -379,7 +379,7 @@ a
|
|||||||
# Sending 'drop function f1'
|
# Sending 'drop function f1'
|
||||||
drop function f1;
|
drop function f1;
|
||||||
# --> connection con2
|
# --> 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
|
# --> connnection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -403,7 +403,7 @@ a
|
|||||||
# Sending 'drop procedure p1'
|
# Sending 'drop procedure p1'
|
||||||
drop procedure p1;
|
drop procedure p1;
|
||||||
# --> connection con2
|
# --> 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
|
# --> connnection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -424,7 +424,7 @@ insert into t1 (a) values (3);
|
|||||||
# Sending 'drop function f2'
|
# Sending 'drop function f2'
|
||||||
drop function f2;
|
drop function f2;
|
||||||
# --> connection con2
|
# --> 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
|
# --> connnection default
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -479,11 +479,11 @@ f2()
|
|||||||
# Sending 'drop function f1'...
|
# Sending 'drop function f1'...
|
||||||
drop function f1;
|
drop function f1;
|
||||||
# --> connection con2
|
# --> 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'...
|
# Sending 'drop function f2'...
|
||||||
drop function f2;
|
drop function f2;
|
||||||
# --> connection default
|
# --> 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;
|
rollback to savepoint sv;
|
||||||
# --> connection con2
|
# --> connection con2
|
||||||
# Reaping 'drop function f2'...
|
# Reaping 'drop function f2'...
|
||||||
@ -537,10 +537,10 @@ f1()
|
|||||||
# Sending 'alter function f1 ...'...
|
# Sending 'alter function f1 ...'...
|
||||||
alter function f1 comment "comment";
|
alter function f1 comment "comment";
|
||||||
# --> connection con2
|
# --> 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()'...
|
# Sending 'call p1()'...
|
||||||
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...
|
# Let 'alter function f1 ...' go through...
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -573,7 +573,7 @@ f1()
|
|||||||
# Sending 'alter function f1 ...'...
|
# Sending 'alter function f1 ...'...
|
||||||
alter function f1 comment "comment";
|
alter function f1 comment "comment";
|
||||||
# --> connection con2
|
# --> 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
|
# We just mention p1() in the body of f2() to make
|
||||||
# sure that p1() is prelocked for f2().
|
# sure that p1() is prelocked for f2().
|
||||||
@ -595,7 +595,7 @@ select f2() into @var;
|
|||||||
end|
|
end|
|
||||||
# Sending 'call p1()'...
|
# Sending 'call p1()'...
|
||||||
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...
|
# Let 'alter function f1 ...' go through...
|
||||||
commit;
|
commit;
|
||||||
# --> connection con1
|
# --> connection con1
|
||||||
@ -634,7 +634,7 @@ get_lock("30977", 0)
|
|||||||
# Sending 'select f3()'...
|
# Sending 'select f3()'...
|
||||||
select f3();
|
select f3();
|
||||||
# --> connection con1
|
# --> 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.
|
# Do something to change the cache version.
|
||||||
create function f4() returns int return 4;
|
create function f4() returns int return 4;
|
||||||
drop function f4;
|
drop function f4;
|
||||||
|
@ -35,7 +35,7 @@ call bug9486();
|
|||||||
show processlist;
|
show processlist;
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# root localhost test Sleep # NULL
|
# 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 Query # NULL show processlist
|
||||||
# root localhost test Sleep # NULL
|
# root localhost test Sleep # NULL
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
@ -60,7 +60,7 @@ let $wait_condition=
|
|||||||
--echo # con1
|
--echo # con1
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
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
|
--source include/wait_condition.inc
|
||||||
SELECT RELEASE_LOCK('Bug#34306');
|
SELECT RELEASE_LOCK('Bug#34306');
|
||||||
--connection con2
|
--connection con2
|
||||||
|
@ -367,14 +367,14 @@ echo
|
|||||||
;
|
;
|
||||||
connection default;
|
connection default;
|
||||||
echo
|
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
|
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
|
--source include/wait_condition.inc
|
||||||
#
|
#
|
||||||
# Expect to see the state 'Waiting for table' for the third connection because the SELECT
|
# Expect to see the state 'Waiting for table metadata lock' for the third
|
||||||
# collides with the WRITE TABLE LOCK.
|
# connection because the SELECT collides with the WRITE TABLE LOCK.
|
||||||
--replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
|
--replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
|
||||||
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
|
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
@ -422,10 +422,10 @@ echo
|
|||||||
;
|
;
|
||||||
connection default;
|
connection default;
|
||||||
echo
|
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
|
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
|
--source include/wait_condition.inc
|
||||||
echo
|
echo
|
||||||
# Expect result:
|
# 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.
|
--echo # Wait until LOCK TABLE is blocked on SQL-level lock.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # We should be able to do UPDATEs and SELECTs within transaction.
|
--echo # We should be able to do UPDATEs and SELECTs within transaction.
|
||||||
update t1 set x=1 where id = 0;
|
update t1 set x=1 where id = 0;
|
||||||
|
@ -28,7 +28,8 @@ ALTER TABLE t1 TRUNCATE PARTITION pMax;
|
|||||||
--echo # con default
|
--echo # con default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
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
|
--source include/wait_condition.inc
|
||||||
--sorted_result
|
--sorted_result
|
||||||
SELECT * FROM t1;
|
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_global_read_lock YES YES
|
||||||
wait/synch/cond/sql/COND_manager YES YES
|
wait/synch/cond/sql/COND_manager YES YES
|
||||||
wait/synch/cond/sql/COND_queue_state 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_rpl_status YES YES
|
||||||
wait/synch/cond/sql/COND_server_started 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_cache YES YES
|
||||||
wait/synch/cond/sql/COND_thread_count 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 YES YES
|
||||||
|
wait/synch/cond/sql/Delayed_insert::cond_client YES YES
|
||||||
select * from performance_schema.SETUP_INSTRUMENTS
|
select * from performance_schema.SETUP_INSTRUMENTS
|
||||||
where name='Wait';
|
where name='Wait';
|
||||||
select * from performance_schema.SETUP_INSTRUMENTS
|
select * from performance_schema.SETUP_INSTRUMENTS
|
||||||
|
@ -182,7 +182,7 @@ count(name)
|
|||||||
select count(name) from COND_INSTANCES
|
select count(name) from COND_INSTANCES
|
||||||
where name like "wait/synch/cond/sql/COND_refresh";
|
where name like "wait/synch/cond/sql/COND_refresh";
|
||||||
count(name)
|
count(name)
|
||||||
1
|
0
|
||||||
select count(name) from COND_INSTANCES
|
select count(name) from COND_INSTANCES
|
||||||
where name like "wait/synch/cond/sql/COND_thread_count";
|
where name like "wait/synch/cond/sql/COND_thread_count";
|
||||||
count(name)
|
count(name)
|
||||||
|
@ -30,7 +30,7 @@ connection master1;
|
|||||||
connection master;
|
connection master;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
ROLLBACK TO SAVEPOINT insert_statement;
|
ROLLBACK TO SAVEPOINT insert_statement;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
@ -655,7 +655,8 @@ connection master;
|
|||||||
connection master1;
|
connection master1;
|
||||||
--echo # Waitng for 'insert into t1 ...' to get blocked on table lock...
|
--echo # Waitng for 'insert into t1 ...' to get blocked on table lock...
|
||||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Sending 'drop function f1'. It will wait till insert finishes.
|
--echo # Sending 'drop function f1'. It will wait till insert finishes.
|
||||||
--send drop function f1;
|
--send drop function f1;
|
||||||
@ -663,7 +664,7 @@ where state='Waiting for table' and info='insert into t1 (a) values (f1())';
|
|||||||
connection default;
|
connection default;
|
||||||
--echo # Check that 'drop function f1' gets blocked.
|
--echo # Check that 'drop function f1' gets blocked.
|
||||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Now let's let 'insert' go through...
|
--echo # Now let's let 'insert' go through...
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
@ -56,7 +56,7 @@ let $wait_condition=
|
|||||||
connection master;
|
connection master;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
select release_lock("lock_bg25144");
|
select release_lock("lock_bg25144");
|
||||||
@ -106,7 +106,7 @@ let $wait_condition=
|
|||||||
connection master;
|
connection master;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter view v1 as select * from t2";
|
||||||
--source include/wait_condition.inc
|
--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
|
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
|
# 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;
|
connection default;
|
||||||
## show processlist info and state ##
|
## show processlist info and state ##
|
||||||
SELECT state,info FROM INFORMATION_SCHEMA.PROCESSLIST
|
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
|
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 ##
|
## table contents befor UNLOCK ##
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
name
|
name
|
||||||
|
@ -11,7 +11,6 @@ CREATE TABLE t1(id int, value varchar(10));
|
|||||||
INSERT INTO t1 VALUES(1, 'val1');
|
INSERT INTO t1 VALUES(1, 'val1');
|
||||||
INSERT INTO t1 VALUES(2, 'val2');
|
INSERT INTO t1 VALUES(2, 'val2');
|
||||||
INSERT INTO t1 VALUES(3, 'val3');
|
INSERT INTO t1 VALUES(3, 'val3');
|
||||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
|
||||||
SET GLOBAL query_cache_size = 131072;
|
SET GLOBAL query_cache_size = 131072;
|
||||||
FLUSHING CACHE
|
FLUSHING CACHE
|
||||||
SET GLOBAL query_cache_size = 0;
|
SET GLOBAL query_cache_size = 0;
|
||||||
@ -33,11 +32,11 @@ SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_queries_in_cache 1
|
Qcache_queries_in_cache 1
|
||||||
1 Expected
|
1 Expected
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_queries_in_cache 1
|
Qcache_queries_in_cache 0
|
||||||
0 Expected
|
0 Expected
|
||||||
'#----------------------------FN_DYNVARS_136_02-----------------------#'
|
'#----------------------------FN_DYNVARS_136_02-----------------------#'
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@ -49,13 +48,12 @@ id value
|
|||||||
2 val2
|
2 val2
|
||||||
3 val3
|
3 val3
|
||||||
** Connection con0 **
|
** Connection con0 **
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
** Connection con1 **
|
** Connection con1 **
|
||||||
** Asynchronous Execution **
|
** Asynchronous Execution **
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
** Connection con0 **
|
** Connection con0 **
|
||||||
wait until table is locked
|
wait until table is locked
|
||||||
Timeout in wait_condition.inc for SELECT count(*) > 0 FROM information_schema.processlist WHERE state= 'Table lock'
|
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
** Connection con1 **
|
** Connection con1 **
|
||||||
** Asynchronous Result **
|
** Asynchronous Result **
|
||||||
@ -79,7 +77,7 @@ SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_queries_in_cache 1
|
Qcache_queries_in_cache 1
|
||||||
1 Expected
|
1 Expected
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
@ -102,7 +100,7 @@ id value
|
|||||||
2 val2
|
2 val2
|
||||||
3 val3
|
3 val3
|
||||||
** Connection con0 **
|
** Connection con0 **
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
** Connection con1 **
|
** Connection con1 **
|
||||||
** Should not be blocked **
|
** Should not be blocked **
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@ -165,4 +163,3 @@ SET @@GLOBAL.query_cache_type = @old_cache_type;
|
|||||||
** Connection default **
|
** Connection default **
|
||||||
Disconnecting Connections con0, con1
|
Disconnecting Connections con0, con1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP VIEW v1;
|
|
||||||
|
@ -98,12 +98,13 @@ INSERT INTO t1(name) VALUES('Record_7');
|
|||||||
connection default;
|
connection default;
|
||||||
# wait until INSERT will be locked (low performance)
|
# wait until INSERT will be locked (low performance)
|
||||||
let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo ## show processlist info and state ##
|
--echo ## show processlist info and state ##
|
||||||
SELECT state,info FROM INFORMATION_SCHEMA.PROCESSLIST
|
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 ##
|
--echo ## table contents befor UNLOCK ##
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
@ -123,7 +123,7 @@ connection default;
|
|||||||
--echo ** Wait till con0 is blocked **
|
--echo ** Wait till con0 is blocked **
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ connection default;
|
|||||||
--echo ** Wait till con0 is blocked **
|
--echo ** Wait till con0 is blocked **
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
@ -60,8 +60,6 @@ INSERT INTO t1 VALUES(1, 'val1');
|
|||||||
INSERT INTO t1 VALUES(2, 'val2');
|
INSERT INTO t1 VALUES(2, 'val2');
|
||||||
INSERT INTO t1 VALUES(3, 'val3');
|
INSERT INTO t1 VALUES(3, 'val3');
|
||||||
|
|
||||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clearing the query cache and setting up cache size
|
# Clearing the query cache and setting up cache size
|
||||||
#
|
#
|
||||||
@ -101,7 +99,7 @@ SELECT * FROM t1;
|
|||||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||||
--echo 1 Expected
|
--echo 1 Expected
|
||||||
|
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
|
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
@ -129,7 +127,7 @@ SELECT * FROM t1;
|
|||||||
--echo ** Connection con0 **
|
--echo ** Connection con0 **
|
||||||
connection con0;
|
connection con0;
|
||||||
|
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
|
|
||||||
--echo ** Connection con1 **
|
--echo ** Connection con1 **
|
||||||
connection con1;
|
connection con1;
|
||||||
@ -141,7 +139,8 @@ send SELECT * FROM t1;
|
|||||||
connection con0;
|
connection con0;
|
||||||
|
|
||||||
--echo wait until table is locked
|
--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
|
--source include/wait_condition.inc
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
@ -177,7 +176,7 @@ SELECT * FROM t1;
|
|||||||
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
SHOW STATUS LIKE 'Qcache_queries_in_cache';
|
||||||
--echo 1 Expected
|
--echo 1 Expected
|
||||||
|
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
|
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
@ -201,7 +200,7 @@ SELECT * FROM t1;
|
|||||||
|
|
||||||
--echo ** Connection con0 **
|
--echo ** Connection con0 **
|
||||||
connection con0;
|
connection con0;
|
||||||
LOCK TABLE v1 WRITE;
|
LOCK TABLE t1 WRITE;
|
||||||
|
|
||||||
--echo ** Connection con1 **
|
--echo ** Connection con1 **
|
||||||
connection con1;
|
connection con1;
|
||||||
@ -283,7 +282,6 @@ disconnect con0;
|
|||||||
disconnect con1;
|
disconnect con1;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP VIEW v1;
|
|
||||||
|
|
||||||
--enable_ps_protocol
|
--enable_ps_protocol
|
||||||
|
|
||||||
|
@ -86,7 +86,9 @@ delimiter ;|
|
|||||||
--echo ** Connection con0 **
|
--echo ** Connection con0 **
|
||||||
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo ** Asynchronous Execution **
|
--echo ** Asynchronous Execution **
|
||||||
@ -102,7 +104,8 @@ delimiter ;|
|
|||||||
--echo ** Connection default **
|
--echo ** Connection default **
|
||||||
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
|
--source include/wait_condition.inc
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
@ -157,7 +160,9 @@ delimiter ;|
|
|||||||
--echo ** Connection con0 **
|
--echo ** Connection con0 **
|
||||||
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo ** Asynchronous Execution **
|
--echo ** Asynchronous Execution **
|
||||||
@ -173,7 +178,8 @@ delimiter ;|
|
|||||||
--echo ** Connection default **
|
--echo ** Connection default **
|
||||||
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
|
--source include/wait_condition.inc
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
--source include/have_thread_concurrency.inc
|
|
||||||
#
|
#
|
||||||
# only global
|
# only global
|
||||||
#
|
#
|
||||||
|
@ -307,7 +307,7 @@ connection update;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
connect (select,localhost,root,,);
|
connect (select,localhost,root,,);
|
||||||
--echo connection: select
|
--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
|
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
|
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
|
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;
|
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;
|
--echo # --> connection default;
|
||||||
connection default;
|
connection default;
|
||||||
unlock tables;
|
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
|
--echo # --> connection con1
|
||||||
connection con1;
|
connection con1;
|
||||||
disconnect con1;
|
disconnect con1;
|
||||||
@ -355,3 +407,142 @@ drop temporary table v1;
|
|||||||
unlock tables;
|
unlock tables;
|
||||||
drop view v2, v3;
|
drop view v2, v3;
|
||||||
drop table t1, v1;
|
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;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # These statements should not be blocked by pending lock requests
|
--echo # These statements should not be blocked by pending lock requests
|
||||||
select table_name, column_name, data_type from information_schema.columns
|
select table_name, column_name, data_type from information_schema.columns
|
||||||
|
@ -89,3 +89,23 @@ from information_schema.referential_constraints
|
|||||||
where constraint_schema = schema();
|
where constraint_schema = schema();
|
||||||
drop table t2;
|
drop table t2;
|
||||||
set foreign_key_checks = 1;
|
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=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||||
WHERE info = "DROP TABLE t1" and
|
WHERE info = "DROP TABLE t1" and
|
||||||
state = "Waiting for table";
|
state = "Waiting for table metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--echo # Connection 1 is now holding the lock.
|
--echo # Connection 1 is now holding the lock.
|
||||||
--echo # Issuing insert from connection 1 while connection 2&3
|
--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.
|
--echo # connection holds SW metadata lock on table to be altered.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # The below statement should succeed. It should not
|
--echo # The below statement should succeed. It should not
|
||||||
@ -196,7 +197,7 @@ connection default;
|
|||||||
--echo # Connection con1
|
--echo # Connection con1
|
||||||
connection con1;
|
connection con1;
|
||||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
@ -241,7 +242,7 @@ connection con2;
|
|||||||
--echo # Waiting for 'SELECT * FROM v1' to sync in.
|
--echo # Waiting for 'SELECT * FROM v1' to sync in.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
# This should block due to v1 being locked.
|
# This should block due to v1 being locked.
|
||||||
--echo # Sending:
|
--echo # Sending:
|
||||||
@ -252,7 +253,8 @@ connection con3;
|
|||||||
--echo # Waiting for 'ALTER VIEW v1 AS SELECT 2 FROM t2' to sync in.
|
--echo # Waiting for 'ALTER VIEW v1 AS SELECT 2 FROM t2' to sync in.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
# Unlock t1 allowing SELECT * FROM v1 to proceed.
|
# Unlock t1 allowing SELECT * FROM v1 to proceed.
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
@ -799,8 +799,9 @@ connection default;
|
|||||||
--echo # table as it acquires LOCK_S locks on rows of old version, which
|
--echo # table as it acquires LOCK_S locks on rows of old version, which
|
||||||
--echo # are compatible with locks acquired by connection 'con1'.
|
--echo # are compatible with locks acquired by connection 'con1'.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist where state =
|
select count(*) = 1 from information_schema.processlist
|
||||||
"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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # The below statement will deadlock because it will try to acquire
|
--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.
|
--echo # Wait until ALTER is blocked because of active SR lock.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # The below statement should succeed as transaction
|
--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
|
# we must wait till the insert opens and locks the table
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
connect (select,localhost,root,,);
|
connect (select,localhost,root,,);
|
||||||
--echo connection: select
|
--echo connection: select
|
||||||
|
@ -357,7 +357,8 @@ let $ID= `select connection_id()`;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
eval kill query $ID;
|
eval kill query $ID;
|
||||||
@ -372,7 +373,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "drop table t1";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -388,7 +389,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "create trigger t1_bi before insert on t1 for each row set @a:=1";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -407,7 +408,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter table t1 add column j int";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -423,7 +424,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter table t1 rename to t2";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -437,7 +438,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter table t1 disable keys";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -452,7 +453,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter table t1 alter column i set default 100";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -474,7 +475,7 @@ connection ddl;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "alter table t2 alter column i set default 100";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
@ -499,7 +500,7 @@ connection ddl;
|
|||||||
connection dml;
|
connection dml;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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";
|
info = "rename tables t1 to t3, t2 to t1";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
let $ID2= `select connection_id()`;
|
let $ID2= `select connection_id()`;
|
||||||
@ -508,7 +509,7 @@ let $ID2= `select connection_id()`;
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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)";
|
info = "insert into t2 values (1)";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID2 ID2
|
--replace_result $ID2 ID2
|
||||||
@ -536,7 +537,7 @@ connection ddl;
|
|||||||
connection dml;
|
connection dml;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Flushing tables" and
|
where state = "Waiting for table flush" and
|
||||||
info = "flush tables";
|
info = "flush tables";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--send select * from t1
|
--send select * from t1
|
||||||
@ -544,7 +545,7 @@ let $wait_condition=
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table" and
|
where state = "Waiting for table flush" and
|
||||||
info = "select * from t1";
|
info = "select * from t1";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--replace_result $ID2 ID2
|
--replace_result $ID2 ID2
|
||||||
|
@ -32,7 +32,8 @@ connection reader;
|
|||||||
# Sleep a bit till the update of connection writer is in work and hangs
|
# Sleep a bit till the update of connection writer is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
send
|
send
|
||||||
select n from t1;
|
select n from t1;
|
||||||
@ -40,7 +41,8 @@ connection locker2;
|
|||||||
# Sleep a bit till the select of connection reader is in work and hangs
|
# Sleep a bit till the select of connection reader is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
select release_lock("mysqltest_lock");
|
select release_lock("mysqltest_lock");
|
||||||
connection locker;
|
connection locker;
|
||||||
@ -72,7 +74,8 @@ connection reader;
|
|||||||
# Sleep a bit till the update of connection writer is in work and hangs
|
# Sleep a bit till the update of connection writer is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
select n from t1;
|
select n from t1;
|
||||||
connection locker2;
|
connection locker2;
|
||||||
@ -120,7 +123,8 @@ insert t1 select * from t2;
|
|||||||
connection locker;
|
connection locker;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
drop table t2;
|
drop table t2;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -145,7 +149,8 @@ connection locker;
|
|||||||
# Sleep a bit till the insert of connection reader is in work and hangs
|
# Sleep a bit till the insert of connection reader is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
drop table t2;
|
drop table t2;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -191,7 +196,7 @@ connection locker;
|
|||||||
# Sleep a bit till the select of connection reader is in work and hangs
|
# Sleep a bit till the select of connection reader is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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";
|
"SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
# Make test case independent from earlier grants.
|
# 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
|
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
# This must not block.
|
# This must not block.
|
||||||
--error ER_TABLE_NOT_LOCKED
|
--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
|
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--error ER_TABLE_NOT_LOCKED
|
--error ER_TABLE_NOT_LOCKED
|
||||||
CREATE TABLE t2 AS SELECT * FROM t1;
|
CREATE TABLE t2 AS SELECT * FROM t1;
|
||||||
@ -326,7 +333,8 @@ connection reader;
|
|||||||
# Wait till connection writer is blocked
|
# Wait till connection writer is blocked
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
send
|
send
|
||||||
alter table t1 auto_increment=0;
|
alter table t1 auto_increment=0;
|
||||||
@ -334,7 +342,8 @@ connection locker;
|
|||||||
# Wait till connection reader is blocked
|
# Wait till connection reader is blocked
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 2 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
unlock tables;
|
unlock tables;
|
||||||
connection writer;
|
connection writer;
|
||||||
@ -367,7 +376,8 @@ connection con5;
|
|||||||
--echo # con5
|
--echo # con5
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # global read lock is taken
|
--echo # global read lock is taken
|
||||||
connection con3;
|
connection con3;
|
||||||
@ -489,16 +499,20 @@ update t1 set i= 10;
|
|||||||
connection reader;
|
connection reader;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
send
|
send
|
||||||
select * from t1;
|
select * from t1;
|
||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--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
|
--replace_result $ID ID
|
||||||
eval kill query $ID;
|
eval kill query $ID;
|
||||||
connection reader;
|
connection reader;
|
||||||
@ -557,7 +571,7 @@ connection default;
|
|||||||
--echo connection: default
|
--echo connection: default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
alter table t1 add column j int;
|
alter table t1 add column j int;
|
||||||
connect (insert,localhost,root,,test,,);
|
connect (insert,localhost,root,,test,,);
|
||||||
@ -565,7 +579,7 @@ connection insert;
|
|||||||
--echo connection: insert
|
--echo connection: insert
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--send insert into t1 values (1,2);
|
--send insert into t1 values (1,2);
|
||||||
--echo connection: default
|
--echo connection: default
|
||||||
@ -615,12 +629,12 @@ connection default;
|
|||||||
--echo connection: default
|
--echo connection: default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
flush tables;
|
flush tables;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
unlock tables;
|
unlock tables;
|
||||||
connection flush;
|
connection flush;
|
||||||
@ -646,7 +660,8 @@ send insert into t1 values(1);
|
|||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
let $tlwb= `show status like 'Table_locks_waited'`;
|
let $tlwb= `show status like 'Table_locks_waited'`;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
@ -683,12 +698,12 @@ connection default;
|
|||||||
--echo connection: default
|
--echo connection: default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
flush tables;
|
flush tables;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
drop table t1;
|
drop table t1;
|
||||||
connection flush;
|
connection flush;
|
||||||
@ -725,7 +740,8 @@ connection default;
|
|||||||
--echo # connection holds SW metadata lock on table to be altered.
|
--echo # connection holds SW metadata lock on table to be altered.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # The below statement should succeed. It should not
|
--echo # The below statement should succeed. It should not
|
||||||
@ -825,7 +841,8 @@ connection default;
|
|||||||
--echo # Wait until ALTER TABLE gets blocked.
|
--echo # Wait until ALTER TABLE gets blocked.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # The below statement should try to acquire SW lock on 't1'
|
--echo # The below statement should try to acquire SW lock on 't1'
|
||||||
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||||
@ -855,7 +872,8 @@ connection default;
|
|||||||
--echo # Wait until ALTER TABLE gets blocked.
|
--echo # Wait until ALTER TABLE gets blocked.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # The below statement should try to acquire SW lock on 't1'
|
--echo # The below statement should try to acquire SW lock on 't1'
|
||||||
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
--echo # and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||||
@ -982,7 +1000,7 @@ connection con3;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--error ER_LOCK_WAIT_TIMEOUT
|
--error ER_LOCK_WAIT_TIMEOUT
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@ -1014,7 +1032,8 @@ connection con3;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
# Note: This query causes two timeouts.
|
# Note: This query causes two timeouts.
|
||||||
# 1: try_acquire_high_prio_shared_mdl_lock on t1
|
# 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'.
|
--echo # Wait until RENAME TABLE is blocked on table 't3'.
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Kill RENAME TABLE.
|
--echo # Kill RENAME TABLE.
|
||||||
--replace_result $ID ID
|
--replace_result $ID ID
|
||||||
|
@ -898,7 +898,7 @@ set debug_sync= 'now WAIT_FOR parked';
|
|||||||
connection default;
|
connection default;
|
||||||
--echo # Wait until this LOCK TABLES statement starts waiting for table lock.
|
--echo # Wait until this LOCK TABLES statement starts waiting for table lock.
|
||||||
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
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';
|
info='lock table v1 write';
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--echo # Allow SELECT ... FOR UPDATE to resume.
|
--echo # Allow SELECT ... FOR UPDATE to resume.
|
||||||
@ -972,7 +972,7 @@ connection default;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
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";
|
AND info = "ALTER TABLE t1 ADD COLUMN j INT";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@ connection default;
|
|||||||
#--sleep 8
|
#--sleep 8
|
||||||
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||||
let $wait_condition= SELECT 1 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
|
--source include/wait_condition.inc
|
||||||
#SELECT NOW();
|
#SELECT NOW();
|
||||||
--echo # Kick INSERT out of thr_multi_lock().
|
--echo # Kick INSERT out of thr_multi_lock().
|
||||||
@ -61,7 +61,7 @@ FLUSH TABLES;
|
|||||||
#--sleep 8
|
#--sleep 8
|
||||||
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
#SELECT ID,STATE,INFO FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||||
let $wait_condition= SELECT 1 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
|
--source include/wait_condition.inc
|
||||||
#SELECT NOW();
|
#SELECT NOW();
|
||||||
--echo # Unlock and close table and wait for con1 to close too.
|
--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.
|
# Wait till "alter table t1 ..." of session changer is in work.
|
||||||
# = There is one session waiting.
|
# = There is one session waiting.
|
||||||
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
send update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
|
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.
|
# are in work.
|
||||||
# = There are two session waiting.
|
# = There are two session waiting.
|
||||||
let $wait_condition= select count(*)= 2 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
|
||||||
|
@ -498,12 +498,20 @@ drop table t1,t2,t3,t4;
|
|||||||
set query_cache_wlock_invalidate=1;
|
set query_cache_wlock_invalidate=1;
|
||||||
create table t1 (a int not null);
|
create table t1 (a int not null);
|
||||||
create table t2 (a int not null);
|
create table t2 (a int not null);
|
||||||
|
create view v1 as select * from t1;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
select * from t2;
|
select * from t2;
|
||||||
show status like "Qcache_queries_in_cache";
|
show status like "Qcache_queries_in_cache";
|
||||||
lock table t1 write, t2 read;
|
lock table t1 write, t2 read;
|
||||||
show status like "Qcache_queries_in_cache";
|
show status like "Qcache_queries_in_cache";
|
||||||
unlock table;
|
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;
|
drop table t1,t2;
|
||||||
set query_cache_wlock_invalidate=default;
|
set query_cache_wlock_invalidate=default;
|
||||||
|
|
||||||
|
@ -58,18 +58,18 @@ connection user3;
|
|||||||
# Typical information_schema.processlist content after sufficient sleep time
|
# Typical information_schema.processlist content after sufficient sleep time
|
||||||
# ID USER COMMAND TIME STATE INFO
|
# 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
|
# XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
# The values marked with 'X' must be reached.
|
# The values marked with 'X' must be reached.
|
||||||
--echo # Poll till the select of connection user1 is blocked by the write lock on t1.
|
--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
|
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';
|
AND info = '$select_for_qc';
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
eval
|
eval
|
||||||
SELECT user,command,state,info FROM information_schema.processlist
|
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';
|
AND info = '$select_for_qc';
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ drop schema foo;
|
|||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
DROP SCHEMA IF EXISTS schema1;
|
DROP SCHEMA IF EXISTS schema1;
|
||||||
DROP SCHEMA IF EXISTS schema2;
|
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
connect(con2, localhost, root);
|
connect(con2, localhost, root);
|
||||||
@ -32,7 +31,6 @@ connect(con2, localhost, root);
|
|||||||
connection default;
|
connection default;
|
||||||
|
|
||||||
CREATE SCHEMA schema1;
|
CREATE SCHEMA schema1;
|
||||||
CREATE SCHEMA schema2;
|
|
||||||
CREATE TABLE schema1.t1 (a INT);
|
CREATE TABLE schema1.t1 (a INT);
|
||||||
|
|
||||||
SET autocommit= FALSE;
|
SET autocommit= FALSE;
|
||||||
@ -45,10 +43,13 @@ connection con2;
|
|||||||
--echo # Connection default
|
--echo # Connection default
|
||||||
connection default;
|
connection default;
|
||||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
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';
|
AND info='DROP SCHEMA schema1';
|
||||||
--source include/wait_condition.inc
|
--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;
|
SET autocommit= TRUE;
|
||||||
|
|
||||||
--echo # Connection 2
|
--echo # Connection 2
|
||||||
@ -57,7 +58,6 @@ connection con2;
|
|||||||
|
|
||||||
--echo # Connection default
|
--echo # Connection default
|
||||||
connection default;
|
connection default;
|
||||||
DROP SCHEMA schema2;
|
|
||||||
disconnect con2;
|
disconnect con2;
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ connection con2;
|
|||||||
--echo # Connection default
|
--echo # Connection default
|
||||||
connection default;
|
connection default;
|
||||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # CREATE SCHEMA used to give a deadlock.
|
--echo # CREATE SCHEMA used to give a deadlock.
|
||||||
@ -124,7 +124,7 @@ connection default;
|
|||||||
--echo # Connection con2
|
--echo # Connection con2
|
||||||
connect (con2, localhost, root);
|
connect (con2, localhost, root);
|
||||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo # Connection con1
|
--echo # Connection con1
|
||||||
@ -172,7 +172,7 @@ connection con2;
|
|||||||
--echo # Connection 3
|
--echo # Connection 3
|
||||||
connection con3;
|
connection con3;
|
||||||
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # But it should still be possible to CREATE/ALTER/DROP other databases.
|
--echo # But it should still be possible to CREATE/ALTER/DROP other databases.
|
||||||
CREATE DATABASE db2;
|
CREATE DATABASE db2;
|
||||||
|
@ -183,18 +183,19 @@ connection con1;
|
|||||||
send drop procedure p1;
|
send drop procedure p1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -222,18 +223,19 @@ connection con1;
|
|||||||
send create procedure p1() begin end;
|
send create procedure p1() begin end;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -259,18 +261,19 @@ connection con1;
|
|||||||
send alter procedure p1 contains sql;
|
send alter procedure p1 contains sql;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -296,18 +299,19 @@ connection con1;
|
|||||||
send drop function f1;
|
send drop function f1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -335,18 +339,19 @@ connection con1;
|
|||||||
send create function f1() returns int return 2;
|
send create function f1() returns int return 2;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -373,18 +378,19 @@ connection con1;
|
|||||||
send alter function f1 contains sql;
|
send alter function f1 contains sql;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Demonstrate that there is a pending exclusive lock.
|
--echo # Demonstrate that there is a pending exclusive lock.
|
||||||
--echo # Sending 'select f1()'...
|
--echo # Sending 'select f1()'...
|
||||||
send select f1();
|
send select f1();
|
||||||
--echo # --> connection con3
|
--echo # --> connection con3
|
||||||
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
|
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
|
--echo # --> connection default
|
||||||
connection default;
|
connection default;
|
||||||
commit;
|
commit;
|
||||||
@ -471,9 +477,10 @@ connection con1;
|
|||||||
send drop function f1;
|
send drop function f1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connnection default
|
--echo # --> connnection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -497,9 +504,10 @@ connection con1;
|
|||||||
send drop function f1;
|
send drop function f1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connnection default
|
--echo # --> connnection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -530,9 +538,10 @@ connection con1;
|
|||||||
send drop procedure p1;
|
send drop procedure p1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connnection default
|
--echo # --> connnection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -561,9 +570,10 @@ connection con1;
|
|||||||
send drop function f2;
|
send drop function f2;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # --> connnection default
|
--echo # --> connnection default
|
||||||
connection default;
|
connection default;
|
||||||
@ -623,17 +633,19 @@ connection con1;
|
|||||||
send drop function f1;
|
send drop function f1;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Sending 'drop function f2'...
|
--echo # Sending 'drop function f2'...
|
||||||
send drop function f2;
|
send drop function f2;
|
||||||
--echo # --> connection default
|
--echo # --> connection default
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
rollback to savepoint sv;
|
rollback to savepoint sv;
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
@ -699,16 +711,18 @@ connection con1;
|
|||||||
send alter function f1 comment "comment";
|
send alter function f1 comment "comment";
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Sending 'call p1()'...
|
--echo # Sending 'call p1()'...
|
||||||
send call p1();
|
send call p1();
|
||||||
connection default;
|
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Let 'alter function f1 ...' go through...
|
--echo # Let 'alter function f1 ...' go through...
|
||||||
commit;
|
commit;
|
||||||
@ -746,9 +760,10 @@ connection con1;
|
|||||||
send alter function f1 comment "comment";
|
send alter function f1 comment "comment";
|
||||||
--echo # --> connection con2
|
--echo # --> connection con2
|
||||||
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
|
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
|
--source include/wait_condition.inc
|
||||||
delimiter |;
|
delimiter |;
|
||||||
--echo #
|
--echo #
|
||||||
@ -774,9 +789,10 @@ delimiter ;|
|
|||||||
--echo # Sending 'call p1()'...
|
--echo # Sending 'call p1()'...
|
||||||
send call p1();
|
send call p1();
|
||||||
connection default;
|
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
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Let 'alter function f1 ...' go through...
|
--echo # Let 'alter function f1 ...' go through...
|
||||||
commit;
|
commit;
|
||||||
@ -825,7 +841,7 @@ connection default;
|
|||||||
send select f3();
|
send select f3();
|
||||||
--echo # --> connection con1
|
--echo # --> connection con1
|
||||||
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
|
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||||
where state='User lock' and info='select f1() into @var';
|
where state='User lock' and info='select f1() into @var';
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
|
@ -322,7 +322,7 @@ set session low_priority_updates=on;
|
|||||||
connection rl_wait;
|
connection rl_wait;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
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'";
|
info = "update t1 set value='updated' where value='old'";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR locked';
|
|||||||
--echo # Connection con3
|
--echo # Connection con3
|
||||||
connection con3;
|
connection con3;
|
||||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
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';
|
AND info='SHOW OPEN TABLES WHERE f1()=0';
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--echo # Check that the IS query is blocked before releasing the x-lock
|
--echo # Check that the IS query is blocked before releasing the x-lock
|
||||||
|
@ -58,7 +58,8 @@ let $ID= `select connection_id()`;
|
|||||||
connection con2;
|
connection con2;
|
||||||
--echo # Switched to connection: con2
|
--echo # Switched to connection: con2
|
||||||
# wait for the other query to start executing
|
# 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
|
--source include/wait_condition.inc
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
|
||||||
|
@ -896,7 +896,7 @@ connection default;
|
|||||||
--echo connection: default
|
--echo connection: default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 1 from information_schema.processlist
|
select count(*) = 1 from information_schema.processlist
|
||||||
where state = "Waiting for table";
|
where state = "Waiting for global metadata lock";
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
create trigger t1_bi before insert on t1 for each row begin end;
|
create trigger t1_bi before insert on t1 for each row begin end;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
|
@ -4074,7 +4074,8 @@ connection default;
|
|||||||
connection con2;
|
connection con2;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # ... then try to drop the view. This should block.
|
--echo # ... then try to drop the view. This should block.
|
||||||
--echo # Sending:
|
--echo # Sending:
|
||||||
@ -4084,7 +4085,7 @@ let $wait_condition=
|
|||||||
connection con3;
|
connection con3;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 from information_schema.processlist
|
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
|
--source include/wait_condition.inc
|
||||||
--echo # Now allow CALL p1() to complete
|
--echo # Now allow CALL p1() to complete
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
@ -428,7 +428,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
|
|||||||
thread_var->current_cond= cond;
|
thread_var->current_cond= cond;
|
||||||
data->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__);
|
__func__, __FILE__, __LINE__);
|
||||||
|
|
||||||
set_timespec(wait_timeout, lock_wait_timeout);
|
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->state = 0;
|
||||||
rwp->waiters = 0;
|
rwp->waiters = 0;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwp->write_thread = 0;
|
||||||
|
#endif
|
||||||
/* If attribute argument is NULL use default value - prefer writers. */
|
/* If attribute argument is NULL use default value - prefer writers. */
|
||||||
rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
|
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)
|
int my_rw_destroy(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(rwp->state == 0);
|
||||||
pthread_mutex_destroy( &rwp->lock );
|
pthread_mutex_destroy( &rwp->lock );
|
||||||
pthread_cond_destroy( &rwp->readers );
|
pthread_cond_destroy( &rwp->readers );
|
||||||
pthread_cond_destroy( &rwp->writers );
|
pthread_cond_destroy( &rwp->writers );
|
||||||
@ -123,10 +127,15 @@ int my_rw_wrlock(my_rw_lock_t *rwp)
|
|||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
rwp->waiters++; /* another writer queued */
|
rwp->waiters++; /* another writer queued */
|
||||||
|
|
||||||
|
my_rw_lock_assert_not_write_owner(rwp);
|
||||||
|
|
||||||
while (rwp->state)
|
while (rwp->state)
|
||||||
pthread_cond_wait(&rwp->writers, &rwp->lock);
|
pthread_cond_wait(&rwp->writers, &rwp->lock);
|
||||||
rwp->state = -1;
|
rwp->state = -1;
|
||||||
rwp->waiters--;
|
rwp->waiters--;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwp->write_thread= pthread_self();
|
||||||
|
#endif
|
||||||
pthread_mutex_unlock(&rwp->lock);
|
pthread_mutex_unlock(&rwp->lock);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@ -142,6 +151,9 @@ int my_rw_trywrlock(my_rw_lock_t *rwp)
|
|||||||
{
|
{
|
||||||
res=0;
|
res=0;
|
||||||
rwp->state = -1;
|
rwp->state = -1;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwp->write_thread= pthread_self();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&rwp->lock);
|
pthread_mutex_unlock(&rwp->lock);
|
||||||
return(res);
|
return(res);
|
||||||
@ -154,9 +166,15 @@ int my_rw_unlock(my_rw_lock_t *rwp)
|
|||||||
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
|
|
||||||
|
DBUG_ASSERT(rwp->state != 0);
|
||||||
|
|
||||||
if (rwp->state == -1) /* writer releasing */
|
if (rwp->state == -1) /* writer releasing */
|
||||||
{
|
{
|
||||||
|
my_rw_lock_assert_write_owner(rwp);
|
||||||
rwp->state= 0; /* mark as available */
|
rwp->state= 0; /* mark as available */
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwp->write_thread= 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( rwp->waiters ) /* writers queued */
|
if ( rwp->waiters ) /* writers queued */
|
||||||
pthread_cond_signal( &rwp->writers );
|
pthread_cond_signal( &rwp->writers );
|
||||||
|
@ -74,6 +74,7 @@ SET (SQL_SOURCE
|
|||||||
sql_profile.cc event_parse_data.cc sql_alter.cc
|
sql_profile.cc event_parse_data.cc sql_alter.cc
|
||||||
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
|
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
|
||||||
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
|
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
|
||||||
|
sql_reload.cc
|
||||||
${GEN_SOURCES}
|
${GEN_SOURCES}
|
||||||
${MYSYS_LIBWRAP_SOURCE})
|
${MYSYS_LIBWRAP_SOURCE})
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ DTRACEFILES = filesort.o \
|
|||||||
sql_cursor.o \
|
sql_cursor.o \
|
||||||
sql_delete.o \
|
sql_delete.o \
|
||||||
sql_truncate.o \
|
sql_truncate.o \
|
||||||
|
sql_reload.o \
|
||||||
sql_insert.o \
|
sql_insert.o \
|
||||||
datadict.o \
|
datadict.o \
|
||||||
sql_parse.o \
|
sql_parse.o \
|
||||||
@ -59,6 +60,7 @@ DTRACEFILES_DEPEND = filesort.o \
|
|||||||
sql_cursor.o \
|
sql_cursor.o \
|
||||||
sql_delete.o \
|
sql_delete.o \
|
||||||
sql_truncate.o \
|
sql_truncate.o \
|
||||||
|
sql_reload.o \
|
||||||
sql_insert.o \
|
sql_insert.o \
|
||||||
datadict.o \
|
datadict.o \
|
||||||
sql_parse.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 \
|
contributors.h sql_servers.h sql_signal.h records.h \
|
||||||
sql_prepare.h rpl_handler.h replication.h mdl.h \
|
sql_prepare.h rpl_handler.h replication.h mdl.h \
|
||||||
sql_plist.h transaction.h sys_vars.h sql_truncate.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 \
|
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||||
item.cc item_sum.cc item_buff.cc item_func.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 \
|
sql_connect.cc scheduler.cc sql_parse.cc \
|
||||||
keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \
|
keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \
|
||||||
sql_base.cc table.cc sql_select.cc sql_insert.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_prepare.cc sql_error.cc sql_locale.cc \
|
||||||
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
|
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
|
||||||
procedure.cc sql_test.cc sql_admin.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);
|
build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
|
||||||
|
|
||||||
/* Attempt to reconstruct the table. */
|
/* Attempt to reconstruct the table. */
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
error= ha_create_table(thd, path, db, table_name, &create_info, TRUE);
|
error= ha_create_table(thd, path, db, table_name, &create_info, TRUE);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
@ -996,24 +996,33 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
|
|||||||
LEX_STRING name, Event_basic *etn)
|
LEX_STRING name, Event_basic *etn)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
TABLE *table= NULL;
|
|
||||||
ulong saved_mode= thd->variables.sql_mode;
|
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_ENTER("Event_db_repository::load_named_event");
|
||||||
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd,
|
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd,
|
||||||
(int) name.length, name.str));
|
(int) name.length, name.str));
|
||||||
|
|
||||||
|
event_table.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
|
||||||
|
|
||||||
/* Reset sql_mode during data dictionary operations. */
|
/* Reset sql_mode during data dictionary operations. */
|
||||||
thd->variables.sql_mode= 0;
|
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);
|
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");
|
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;
|
thd->variables.sql_mode= saved_mode;
|
||||||
|
@ -699,7 +699,6 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
|
|||||||
bool
|
bool
|
||||||
Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
||||||
{
|
{
|
||||||
Open_tables_backup open_tables_backup;
|
|
||||||
Event_timed et;
|
Event_timed et;
|
||||||
bool ret;
|
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'
|
deadlock can occur please refer to the description of 'system table'
|
||||||
flag.
|
flag.
|
||||||
*/
|
*/
|
||||||
thd->reset_n_backup_open_tables_state(&open_tables_backup);
|
|
||||||
ret= db_repository->load_named_event(thd, dbname, name, &et);
|
ret= db_repository->load_named_event(thd, dbname, name, &et);
|
||||||
thd->restore_backup_open_tables_state(&open_tables_backup);
|
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret= send_show_create_event(thd, &et, thd->protocol);
|
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));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= m_dbname;
|
table_list.db= m_dbname;
|
||||||
table_list.alias= table_list.table_name= m_tabname;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -5702,7 +5702,7 @@ int ha_ndbcluster::create(const char *name,
|
|||||||
m_table->getObjectVersion(),
|
m_table->getObjectVersion(),
|
||||||
(is_truncate) ?
|
(is_truncate) ?
|
||||||
SOT_TRUNCATE_TABLE : SOT_CREATE_TABLE,
|
SOT_TRUNCATE_TABLE : SOT_CREATE_TABLE,
|
||||||
0, 0, 1);
|
0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6143,7 +6143,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
|||||||
old_dbname, m_tabname,
|
old_dbname, m_tabname,
|
||||||
ndb_table_id, ndb_table_version,
|
ndb_table_id, ndb_table_version,
|
||||||
SOT_RENAME_TABLE,
|
SOT_RENAME_TABLE,
|
||||||
m_dbname, new_tabname, 1);
|
m_dbname, new_tabname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are moving tables between databases, we need to recreate
|
// If we are moving tables between databases, we need to recreate
|
||||||
@ -6337,7 +6337,7 @@ retry_temporary_error1:
|
|||||||
thd->query(), thd->query_length(),
|
thd->query(), thd->query_length(),
|
||||||
share->db, share->table_name,
|
share->db, share->table_name,
|
||||||
ndb_table_id, ndb_table_version,
|
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
|
else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op
|
||||||
will do a force GCP */
|
will do a force GCP */
|
||||||
@ -7019,7 +7019,6 @@ int ndbcluster_drop_database_impl(const char *path)
|
|||||||
while ((tabname=it++))
|
while ((tabname=it++))
|
||||||
{
|
{
|
||||||
tablename_to_filename(tabname, tmp, FN_REFLEN - (tmp - full_path)-1);
|
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))
|
if (ha_ndbcluster::delete_table(0, ndb, full_path, dbname, tabname))
|
||||||
{
|
{
|
||||||
const NdbError err= dict->getNdbError();
|
const NdbError err= dict->getNdbError();
|
||||||
@ -7029,7 +7028,6 @@ int ndbcluster_drop_database_impl(const char *path)
|
|||||||
ret= ndb_to_mysql_error(&err);
|
ret= ndb_to_mysql_error(&err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -7056,7 +7054,7 @@ static void ndbcluster_drop_database(handlerton *hton, char *path)
|
|||||||
ha_ndbcluster::set_dbname(path, db);
|
ha_ndbcluster::set_dbname(path, db);
|
||||||
ndbcluster_log_schema_op(thd, 0,
|
ndbcluster_log_schema_op(thd, 0,
|
||||||
thd->query(), thd->query_length(),
|
thd->query(), thd->query_length(),
|
||||||
db, "", 0, 0, SOT_DROP_DB, 0, 0, 0);
|
db, "", 0, 0, SOT_DROP_DB, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -7181,7 +7179,6 @@ int ndbcluster_find_all_files(THD *thd)
|
|||||||
my_free(data);
|
my_free(data);
|
||||||
my_free(pack_data);
|
my_free(pack_data);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
if (discover)
|
if (discover)
|
||||||
{
|
{
|
||||||
/* ToDo 4.1 database needs to be created if missing */
|
/* ToDo 4.1 database needs to be created if missing */
|
||||||
@ -7199,7 +7196,6 @@ int ndbcluster_find_all_files(THD *thd)
|
|||||||
TRUE);
|
TRUE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (unhandled && retries);
|
while (unhandled && retries);
|
||||||
@ -7292,19 +7288,16 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
|||||||
file_name->str, reg_ext, 0);
|
file_name->str, reg_ext, 0);
|
||||||
if (my_access(name, F_OK))
|
if (my_access(name, F_OK))
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
DBUG_PRINT("info", ("Table %s listed and need discovery",
|
DBUG_PRINT("info", ("Table %s listed and need discovery",
|
||||||
file_name->str));
|
file_name->str));
|
||||||
if (ndb_create_table_from_engine(thd, db, 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,
|
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_TABLE_EXISTS_ERROR,
|
ER_TABLE_EXISTS_ERROR,
|
||||||
"Discover of table %s.%s failed",
|
"Discover of table %s.%s failed",
|
||||||
db, file_name->str);
|
db, file_name->str);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name->str));
|
DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name->str));
|
||||||
file_on_disk= TRUE;
|
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);
|
file_name_str= (char*)my_hash_element(&ok_tables, i);
|
||||||
end= end1 +
|
end= end1 +
|
||||||
tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name));
|
tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name));
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
ndbcluster_create_binlog_setup(ndb, name, end-name,
|
ndbcluster_create_binlog_setup(ndb, name, end-name,
|
||||||
db, file_name_str, TRUE);
|
db, file_name_str, TRUE);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -7426,7 +7417,6 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Lock mutex before creating .FRM files. */
|
/* Lock mutex before creating .FRM files. */
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
/* Create new files. */
|
/* Create new files. */
|
||||||
List_iterator_fast<char> it2(create_list);
|
List_iterator_fast<char> it2(create_list);
|
||||||
while ((file_name_str=it2++))
|
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(&ok_tables);
|
||||||
my_hash_free(&ndb_tables);
|
my_hash_free(&ndb_tables);
|
||||||
|
|
||||||
@ -8452,8 +8440,7 @@ int handle_trailing_share(NDB_SHARE *share)
|
|||||||
bzero((char*) &table_list,sizeof(table_list));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= share->db;
|
table_list.db= share->db;
|
||||||
table_list.alias= table_list.table_name= share->table_name;
|
table_list.alias= table_list.table_name= share->table_name;
|
||||||
mysql_mutex_assert_owner(&LOCK_open);
|
close_cached_tables(thd, &table_list, FALSE, LONG_TIMEOUT);
|
||||||
close_cached_tables(thd, &table_list, TRUE, FALSE);
|
|
||||||
|
|
||||||
mysql_mutex_lock(&ndbcluster_mutex);
|
mysql_mutex_lock(&ndbcluster_mutex);
|
||||||
/* ndb_share reference temporary free */
|
/* ndb_share reference temporary free */
|
||||||
@ -10612,13 +10599,13 @@ int ndbcluster_alter_tablespace(handlerton *hton,
|
|||||||
thd->query(), thd->query_length(),
|
thd->query(), thd->query_length(),
|
||||||
"", alter_info->tablespace_name,
|
"", alter_info->tablespace_name,
|
||||||
0, 0,
|
0, 0,
|
||||||
SOT_TABLESPACE, 0, 0, 0);
|
SOT_TABLESPACE, 0, 0);
|
||||||
else
|
else
|
||||||
ndbcluster_log_schema_op(thd, 0,
|
ndbcluster_log_schema_op(thd, 0,
|
||||||
thd->query(), thd->query_length(),
|
thd->query(), thd->query_length(),
|
||||||
"", alter_info->logfile_group_name,
|
"", alter_info->logfile_group_name,
|
||||||
0, 0,
|
0, 0,
|
||||||
SOT_LOGFILE_GROUP, 0, 0, 0);
|
SOT_LOGFILE_GROUP, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
@ -360,7 +360,6 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share,
|
|||||||
int error;
|
int error;
|
||||||
DBUG_ENTER("ndbcluster_binlog_open_table");
|
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,
|
init_tmp_table_share(thd, table_share, share->db, 0, share->table_name,
|
||||||
share->key);
|
share->key);
|
||||||
if ((error= open_table_def(thd, table_share, 0)))
|
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);
|
free_table_share(table_share);
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
mysql_mutex_lock(&LOCK_open);
|
||||||
assign_new_table_id(table_share);
|
assign_new_table_id(table_share);
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
|
|
||||||
if (!reopen)
|
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,
|
ndbcluster_log_schema_op(thd, 0, query, query_length,
|
||||||
db, table_name, 0, 0, type,
|
db, table_name, 0, 0, type,
|
||||||
0, 0, 0);
|
0, 0);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -908,9 +909,7 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
|
|||||||
if (!ndb_schema_share &&
|
if (!ndb_schema_share &&
|
||||||
ndbcluster_check_ndb_schema_share() == 0)
|
ndbcluster_check_ndb_schema_share() == 0)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_SCHEMA_TABLE);
|
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_SCHEMA_TABLE);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
if (!ndb_schema_share)
|
if (!ndb_schema_share)
|
||||||
{
|
{
|
||||||
ndbcluster_create_schema_table(thd);
|
ndbcluster_create_schema_table(thd);
|
||||||
@ -922,9 +921,7 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
|
|||||||
if (!ndb_apply_status_share &&
|
if (!ndb_apply_status_share &&
|
||||||
ndbcluster_check_ndb_apply_status_share() == 0)
|
ndbcluster_check_ndb_apply_status_share() == 0)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_APPLY_TABLE);
|
ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_APPLY_TABLE);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
if (!ndb_apply_status_share)
|
if (!ndb_apply_status_share)
|
||||||
{
|
{
|
||||||
ndbcluster_create_ndb_apply_status_table(thd);
|
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))
|
if (!ndbcluster_find_all_files(thd))
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
ndb_binlog_tables_inited= TRUE;
|
ndb_binlog_tables_inited= TRUE;
|
||||||
if (opt_ndb_extra_logging)
|
if (opt_ndb_extra_logging)
|
||||||
sql_print_information("NDB Binlog: ndb tables writable");
|
sql_print_information("NDB Binlog: ndb tables writable");
|
||||||
close_cached_tables(NULL, NULL, TRUE, FALSE);
|
close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
/* Signal injector thread that all is setup */
|
/* Signal injector thread that all is setup */
|
||||||
mysql_cond_signal(&injector_cond);
|
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_id,
|
||||||
uint32 ndb_table_version,
|
uint32 ndb_table_version,
|
||||||
enum SCHEMA_OP_TYPE type,
|
enum SCHEMA_OP_TYPE type,
|
||||||
const char *new_db, const char *new_table_name,
|
const char *new_db, const char *new_table_name)
|
||||||
int have_lock_open)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ndbcluster_log_schema_op");
|
DBUG_ENTER("ndbcluster_log_schema_op");
|
||||||
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
||||||
@ -1580,11 +1574,6 @@ end:
|
|||||||
|
|
||||||
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
||||||
mysql_mutex_lock(&ndb_schema_object->mutex);
|
mysql_mutex_lock(&ndb_schema_object->mutex);
|
||||||
if (have_lock_open)
|
|
||||||
{
|
|
||||||
mysql_mutex_assert_owner(&LOCK_open);
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
struct timespec abstime;
|
struct timespec abstime;
|
||||||
@ -1640,10 +1629,6 @@ end:
|
|||||||
"distributing", ndb_schema_object->key);
|
"distributing", ndb_schema_object->key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (have_lock_open)
|
|
||||||
{
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
}
|
|
||||||
mysql_mutex_unlock(&ndb_schema_object->mutex);
|
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(),
|
DBUG_DUMP("frm", (uchar*) altered_table->getFrmData(),
|
||||||
altered_table->getFrmLength());
|
altered_table->getFrmLength());
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
Ndb_table_guard ndbtab_g(dict, tabname);
|
Ndb_table_guard ndbtab_g(dict, tabname);
|
||||||
const NDBTAB *old= ndbtab_g.get_table();
|
const NDBTAB *old= ndbtab_g.get_table();
|
||||||
if (!old &&
|
if (!old &&
|
||||||
@ -1752,7 +1736,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
|||||||
bzero((char*) &table_list,sizeof(table_list));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= (char *)dbname;
|
table_list.db= (char *)dbname;
|
||||||
table_list.alias= table_list.table_name= (char *)tabname;
|
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,
|
if ((error= ndbcluster_binlog_open_table(thd, share,
|
||||||
table_share, table, 1)))
|
table_share, table, 1)))
|
||||||
@ -1763,8 +1747,6 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
|
|||||||
table_share= share->table_share;
|
table_share= share->table_share;
|
||||||
dbname= table_share->db.str;
|
dbname= table_share->db.str;
|
||||||
tabname= table_share->table_name.str;
|
tabname= table_share->table_name.str;
|
||||||
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
my_free(data);
|
my_free(data);
|
||||||
my_free(pack_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));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= (char *)dbname;
|
table_list.db= (char *)dbname;
|
||||||
table_list.alias= table_list.table_name= (char *)tabname;
|
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 */
|
/* ndb_share reference create free */
|
||||||
DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u",
|
DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u",
|
||||||
share->key, share->use_count));
|
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));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= schema->db;
|
table_list.db= schema->db;
|
||||||
table_list.alias= table_list.table_name= schema->name;
|
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 */
|
/* ndb_share reference temporary free */
|
||||||
if (share)
|
if (share)
|
||||||
@ -1991,7 +1973,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
|
|||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case SOT_CREATE_TABLE:
|
case SOT_CREATE_TABLE:
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'",
|
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);
|
print_could_not_discover_error(thd, schema);
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
log_query= 1;
|
log_query= 1;
|
||||||
break;
|
break;
|
||||||
case SOT_DROP_DB:
|
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);
|
mysql_mutex_unlock(&ndb_schema_share_mutex);
|
||||||
/* end protect ndb_schema_share */
|
/* end protect ndb_schema_share */
|
||||||
|
|
||||||
close_cached_tables(NULL, NULL, FALSE, FALSE);
|
close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT);
|
||||||
// fall through
|
// fall through
|
||||||
case NDBEVENT::TE_ALTER:
|
case NDBEVENT::TE_ALTER:
|
||||||
ndb_handle_schema_change(thd, ndb, pOp, tmp_share);
|
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));
|
bzero((char*) &table_list,sizeof(table_list));
|
||||||
table_list.db= schema->db;
|
table_list.db= schema->db;
|
||||||
table_list.alias= table_list.table_name= schema->name;
|
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)
|
if (schema_type != SOT_ALTER_TABLE)
|
||||||
break;
|
break;
|
||||||
@ -2274,7 +2254,6 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
|
|||||||
free_share(&share);
|
free_share(&share);
|
||||||
share= 0;
|
share= 0;
|
||||||
}
|
}
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
if (ndbcluster_check_if_local_table(schema->db, schema->name))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'",
|
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);
|
print_could_not_discover_error(thd, schema);
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -3154,8 +3132,6 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
|||||||
#ifdef SYNC_DROP_
|
#ifdef SYNC_DROP_
|
||||||
thd->proc_info= "Syncing ndb table schema operation and binlog";
|
thd->proc_info= "Syncing ndb table schema operation and binlog";
|
||||||
mysql_mutex_lock(&share->mutex);
|
mysql_mutex_lock(&share->mutex);
|
||||||
mysql_mutex_assert_owner(&LOCK_open);
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
int max_timeout= DEFAULT_SYNC_TIMEOUT;
|
||||||
while (share->op)
|
while (share->op)
|
||||||
{
|
{
|
||||||
@ -3181,7 +3157,6 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
|||||||
type_str, share->key);
|
type_str, share->key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
mysql_mutex_unlock(&share->mutex);
|
mysql_mutex_unlock(&share->mutex);
|
||||||
#else
|
#else
|
||||||
mysql_mutex_lock(&share->mutex);
|
mysql_mutex_lock(&share->mutex);
|
||||||
@ -3963,9 +3938,9 @@ restart:
|
|||||||
!ndb_binlog_running))
|
!ndb_binlog_running))
|
||||||
break; /* Shutting down server */
|
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);
|
trans_commit_stmt(thd);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
@ -158,8 +158,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
|
|||||||
uint32 ndb_table_version,
|
uint32 ndb_table_version,
|
||||||
enum SCHEMA_OP_TYPE type,
|
enum SCHEMA_OP_TYPE type,
|
||||||
const char *new_db,
|
const char *new_db,
|
||||||
const char *new_table_name,
|
const char *new_table_name);
|
||||||
int have_lock_open);
|
|
||||||
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
|
||||||
NDB_SHARE *share,
|
NDB_SHARE *share,
|
||||||
const char *type_str);
|
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);
|
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()
|
void st_ha_check_opt::init()
|
||||||
{
|
{
|
||||||
flags= sql_flags= 0;
|
flags= sql_flags= 0;
|
||||||
|
@ -2119,6 +2119,8 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
|
|||||||
|
|
||||||
/* discovery */
|
/* discovery */
|
||||||
int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
|
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,
|
int ha_discover(THD* thd, const char* dbname, const char* name,
|
||||||
uchar** frmblob, size_t* frmlen);
|
uchar** frmblob, size_t* frmlen);
|
||||||
int ha_find_files(THD *thd,const char *db,const char *path,
|
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
|
TODO/FIXME: Dmitry thinks that we broadcast on COND_global_read_lock
|
||||||
did not reach its target. A condition for this was that the same
|
when old instance of table is closed to avoid races
|
||||||
condition variable was used with different mutexes in
|
between incrementing refresh_version and
|
||||||
mysql_cond_wait(). Some time ago we changed LOCK_open to
|
wait_if_global_read_lock(thd, TRUE, FALSE) call.
|
||||||
LOCK_global_read_lock in global read lock handling. So COND_refresh
|
Once global read lock implementation starts using MDL
|
||||||
was used with LOCK_open and LOCK_global_read_lock.
|
infrastructure this will became unnecessary and should
|
||||||
|
be removed.
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void broadcast_refresh(void)
|
void broadcast_refresh(void)
|
||||||
{
|
{
|
||||||
mysql_cond_broadcast(&COND_refresh);
|
|
||||||
mysql_cond_broadcast(&COND_global_read_lock);
|
mysql_cond_broadcast(&COND_global_read_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
sql/lock.h
42
sql/lock.h
@ -9,48 +9,6 @@ struct TABLE_LIST;
|
|||||||
class THD;
|
class THD;
|
||||||
typedef struct st_mysql_lock MYSQL_LOCK;
|
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);
|
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags);
|
||||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
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);
|
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;
|
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
|
A context of the recursive traversal through all contexts
|
||||||
in all sessions in search for deadlock.
|
in all sessions in search for deadlock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Deadlock_detection_visitor
|
class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Deadlock_detection_visitor(MDL_context *start_node_arg)
|
Deadlock_detection_visitor(MDL_context *start_node_arg)
|
||||||
: m_start_node(start_node_arg),
|
: m_start_node(start_node_arg),
|
||||||
m_victim(NULL),
|
m_victim(NULL),
|
||||||
m_current_search_depth(0)
|
m_current_search_depth(0),
|
||||||
|
m_found_deadlock(FALSE)
|
||||||
{}
|
{}
|
||||||
bool enter_node(MDL_context * /* unused */);
|
virtual bool enter_node(MDL_context *node);
|
||||||
void leave_node(MDL_context * /* unused */);
|
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; }
|
MDL_context *get_victim() const { return m_victim; }
|
||||||
|
private:
|
||||||
/**
|
/**
|
||||||
Change the deadlock victim to a new one if it has lower deadlock
|
Change the deadlock victim to a new one if it has lower deadlock
|
||||||
weight.
|
weight.
|
||||||
*/
|
*/
|
||||||
MDL_context *opt_change_victim_to(MDL_context *new_victim);
|
void opt_change_victim_to(MDL_context *new_victim);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
The context which has initiated the search. There
|
The context which has initiated the search. There
|
||||||
@ -145,6 +154,8 @@ private:
|
|||||||
loop.
|
loop.
|
||||||
*/
|
*/
|
||||||
uint m_current_search_depth;
|
uint m_current_search_depth;
|
||||||
|
/** TRUE if we found a deadlock. */
|
||||||
|
bool m_found_deadlock;
|
||||||
/**
|
/**
|
||||||
Maximum depth for deadlock searches. After this depth is
|
Maximum depth for deadlock searches. After this depth is
|
||||||
achieved we will unconditionally declare that there is a
|
achieved we will unconditionally declare that there is a
|
||||||
@ -167,29 +178,38 @@ private:
|
|||||||
a node is entered, inspect_edge() will be called
|
a node is entered, inspect_edge() will be called
|
||||||
for all wait-for destinations of this node. Then
|
for all wait-for destinations of this node. Then
|
||||||
leave_node() will be called.
|
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.
|
including the starting node.
|
||||||
|
|
||||||
@retval TRUE Maximum search depth exceeded.
|
@retval TRUE Maximum search depth exceeded.
|
||||||
@retval FALSE OK.
|
@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)
|
m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
|
||||||
return TRUE;
|
if (m_found_deadlock)
|
||||||
return FALSE;
|
{
|
||||||
|
DBUG_ASSERT(! m_victim);
|
||||||
|
opt_change_victim_to(node);
|
||||||
|
}
|
||||||
|
return m_found_deadlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Done inspecting this node. Decrease the search
|
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;
|
--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)
|
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.
|
@retval !new_victim New victim became the current.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MDL_context *
|
void
|
||||||
Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
|
Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
|
||||||
{
|
{
|
||||||
if (m_victim == NULL ||
|
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. */
|
/* Swap victims, unlock the old one. */
|
||||||
MDL_context *tmp= m_victim;
|
MDL_context *tmp= m_victim;
|
||||||
m_victim= new_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);
|
void remove_ticket(Ticket_list MDL_lock::*queue, MDL_ticket *ticket);
|
||||||
|
|
||||||
bool find_deadlock(MDL_ticket *waiting_ticket,
|
bool visit_subgraph(MDL_ticket *waiting_ticket,
|
||||||
Deadlock_detection_visitor *dvisitor);
|
MDL_wait_for_graph_visitor *gvisitor);
|
||||||
|
|
||||||
/** List of granted tickets for this lock. */
|
/** List of granted tickets for this lock. */
|
||||||
Ticket_list m_granted;
|
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.
|
the associated condition variable: LOCK_mdl and COND_mdl.
|
||||||
These locking primitives are implementation details of the MDL
|
These locking primitives are implementation details of the MDL
|
||||||
subsystem and are private to it.
|
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()
|
void mdl_init()
|
||||||
@ -876,8 +889,8 @@ void MDL_ticket::destroy(MDL_ticket *ticket)
|
|||||||
uint MDL_ticket::get_deadlock_weight() const
|
uint MDL_ticket::get_deadlock_weight() const
|
||||||
{
|
{
|
||||||
return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
|
return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
|
||||||
m_type > MDL_SHARED_NO_WRITE ?
|
m_type >= MDL_SHARED_NO_WRITE ?
|
||||||
MDL_DEADLOCK_WEIGHT_DDL : MDL_DEADLOCK_WEIGHT_DML);
|
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.
|
Wait for the status to be assigned to this wait slot.
|
||||||
|
|
||||||
@param abs_timeout Absolute time after which waiting should stop.
|
@param abs_timeout Absolute time after which waiting should stop.
|
||||||
@param set_status_on_tiemout TRUE - If in case of timeout waiting
|
@param set_status_on_timeout TRUE - If in case of timeout waiting
|
||||||
context should close the wait slot by
|
context should close the wait slot by
|
||||||
sending TIMEOUT to itself.
|
sending TIMEOUT to itself.
|
||||||
FALSE - Otherwise.
|
FALSE - Otherwise.
|
||||||
|
@param wait_state_name Thread state name to be set for duration of wait.
|
||||||
|
|
||||||
@returns Signal posted.
|
@returns Signal posted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MDL_wait::enum_wait_status
|
MDL_wait::enum_wait_status
|
||||||
MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout,
|
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;
|
const char *old_msg;
|
||||||
enum_wait_status result;
|
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);
|
mysql_mutex_lock(&m_LOCK_wait_status);
|
||||||
|
|
||||||
old_msg= thd_enter_cond(thd, &m_COND_wait_status, &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) &&
|
while (!m_wait_status && !thd_killed(thd) &&
|
||||||
wait_result != ETIMEDOUT && wait_result != ETIME)
|
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
|
Check if ticket represents metadata lock of "stronger" or equal type
|
||||||
than specified one. I.e. if metadata lock represented by ticket won't
|
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;
|
MDL_ticket *ticket;
|
||||||
bool is_transactional;
|
bool is_transactional;
|
||||||
|
|
||||||
DBUG_ASSERT(mdl_request->type < MDL_SHARED_NO_WRITE ||
|
DBUG_ASSERT(mdl_request->type != MDL_EXCLUSIVE ||
|
||||||
(is_lock_owner(MDL_key::GLOBAL, "", "",
|
is_lock_owner(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE));
|
||||||
MDL_INTENTION_EXCLUSIVE)));
|
|
||||||
DBUG_ASSERT(mdl_request->ticket == NULL);
|
DBUG_ASSERT(mdl_request->ticket == NULL);
|
||||||
|
|
||||||
/* Don't take chances in production. */
|
/* 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)
|
while (cmp_timespec(abs_shortwait, abs_timeout) <= 0)
|
||||||
{
|
{
|
||||||
/* abs_timeout is far away. Wait a short while and notify locks. */
|
/* 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)
|
if (wait_status != MDL_wait::EMPTY)
|
||||||
break;
|
break;
|
||||||
@ -1757,10 +1780,12 @@ MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
|
|||||||
set_timespec(abs_shortwait, 1);
|
set_timespec(abs_shortwait, 1);
|
||||||
}
|
}
|
||||||
if (wait_status == MDL_wait::EMPTY)
|
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
|
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();
|
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_ticket *ticket;
|
||||||
MDL_context *src_ctx= waiting_ticket->get_ctx();
|
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
|
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.
|
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;
|
goto end;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2036,7 +2070,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
|||||||
/* Filter out edges that point to the same node. */
|
/* Filter out edges that point to the same node. */
|
||||||
if (ticket->get_ctx() != src_ctx &&
|
if (ticket->get_ctx() != src_ctx &&
|
||||||
ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
|
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;
|
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. */
|
/* Filter out edges that point to the same node. */
|
||||||
if (ticket->get_ctx() != src_ctx &&
|
if (ticket->get_ctx() != src_ctx &&
|
||||||
ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
|
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;
|
goto end_leave_node;
|
||||||
}
|
}
|
||||||
@ -2059,7 +2093,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
|||||||
{
|
{
|
||||||
if (ticket->get_ctx() != src_ctx &&
|
if (ticket->get_ctx() != src_ctx &&
|
||||||
ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
|
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;
|
goto end_leave_node;
|
||||||
}
|
}
|
||||||
@ -2070,7 +2104,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
|||||||
{
|
{
|
||||||
if (ticket->get_ctx() != src_ctx &&
|
if (ticket->get_ctx() != src_ctx &&
|
||||||
ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
|
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;
|
goto end_leave_node;
|
||||||
}
|
}
|
||||||
@ -2079,7 +2113,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
|||||||
result= FALSE;
|
result= FALSE;
|
||||||
|
|
||||||
end_leave_node:
|
end_leave_node:
|
||||||
dvisitor->leave_node(src_ctx);
|
gvisitor->leave_node(src_ctx);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
mysql_prlock_unlock(&m_rwlock);
|
mysql_prlock_unlock(&m_rwlock);
|
||||||
@ -2088,35 +2122,47 @@ end:
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Recursively traverse the wait-for graph of MDL contexts
|
Traverse a portion of wait-for graph which is reachable
|
||||||
in search for deadlocks.
|
through the edge represented by this ticket and search
|
||||||
|
for deadlocks.
|
||||||
|
|
||||||
@retval TRUE A deadlock is found. A victim is remembered
|
@retval TRUE A deadlock is found. A pointer to deadlock
|
||||||
by the visitor.
|
victim is saved in the visitor.
|
||||||
@retval FALSE
|
@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;
|
bool result= FALSE;
|
||||||
|
|
||||||
mysql_prlock_rdlock(&m_LOCK_waiting_for);
|
mysql_prlock_rdlock(&m_LOCK_waiting_for);
|
||||||
|
|
||||||
if (m_waiting_for)
|
if (m_waiting_for)
|
||||||
{
|
result= m_waiting_for->accept_visitor(gvisitor);
|
||||||
result= m_waiting_for->m_lock->find_deadlock(m_waiting_for, dvisitor);
|
|
||||||
if (result)
|
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||||
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);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2138,14 +2184,14 @@ void MDL_context::find_deadlock()
|
|||||||
while (1)
|
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,
|
search performed by find_deadlock() below is important,
|
||||||
the code responsible for victim selection relies on this.
|
the code responsible for victim selection relies on this.
|
||||||
*/
|
*/
|
||||||
Deadlock_detection_visitor dvisitor(this);
|
Deadlock_detection_visitor dvisitor(this);
|
||||||
MDL_context *victim;
|
MDL_context *victim;
|
||||||
|
|
||||||
if (! find_deadlock(&dvisitor))
|
if (! visit_subgraph(&dvisitor))
|
||||||
{
|
{
|
||||||
/* No deadlocks are found! */
|
/* No deadlocks are found! */
|
||||||
break;
|
break;
|
||||||
@ -2166,7 +2212,7 @@ void MDL_context::find_deadlock()
|
|||||||
context was waiting is concurrently satisfied.
|
context was waiting is concurrently satisfied.
|
||||||
*/
|
*/
|
||||||
(void) victim->m_wait.set_status(MDL_wait::VICTIM);
|
(void) victim->m_wait.set_status(MDL_wait::VICTIM);
|
||||||
mysql_prlock_unlock(&victim->m_LOCK_waiting_for);
|
victim->unlock_deadlock_victim();
|
||||||
|
|
||||||
if (victim == this)
|
if (victim == this)
|
||||||
break;
|
break;
|
||||||
|
99
sql/mdl.h
99
sql/mdl.h
@ -34,7 +34,6 @@ class THD;
|
|||||||
class MDL_context;
|
class MDL_context;
|
||||||
class MDL_lock;
|
class MDL_lock;
|
||||||
class MDL_ticket;
|
class MDL_ticket;
|
||||||
class Deadlock_detection_visitor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Type of metadata lock request.
|
Type of metadata lock request.
|
||||||
@ -184,7 +183,9 @@ public:
|
|||||||
TABLE,
|
TABLE,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
PROCEDURE,
|
PROCEDURE,
|
||||||
TRIGGER };
|
TRIGGER,
|
||||||
|
/* This should be the last ! */
|
||||||
|
NAMESPACE_END };
|
||||||
|
|
||||||
const uchar *ptr() const { return (uchar*) m_ptr; }
|
const uchar *ptr() const { return (uchar*) m_ptr; }
|
||||||
uint length() const { return m_length; }
|
uint length() const { return m_length; }
|
||||||
@ -251,10 +252,20 @@ public:
|
|||||||
}
|
}
|
||||||
MDL_key() {} /* To use when part of MDL_request. */
|
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:
|
private:
|
||||||
uint16 m_length;
|
uint16 m_length;
|
||||||
uint16 m_db_name_length;
|
uint16 m_db_name_length;
|
||||||
char m_ptr[MAX_MDLKEY_LENGTH];
|
char m_ptr[MAX_MDLKEY_LENGTH];
|
||||||
|
static const char * m_namespace_to_wait_state_name[NAMESPACE_END];
|
||||||
private:
|
private:
|
||||||
MDL_key(const MDL_key &); /* not implemented */
|
MDL_key(const MDL_key &); /* not implemented */
|
||||||
MDL_key &operator=(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 *);
|
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.
|
A granted metadata lock.
|
||||||
|
|
||||||
@ -380,7 +444,7 @@ typedef void (*mdl_cached_object_release_hook)(void *);
|
|||||||
threads/contexts.
|
threads/contexts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MDL_ticket
|
class MDL_ticket : public MDL_wait_for_subgraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -414,8 +478,9 @@ public:
|
|||||||
bool is_incompatible_when_granted(enum_mdl_type type) const;
|
bool is_incompatible_when_granted(enum_mdl_type type) const;
|
||||||
bool is_incompatible_when_waiting(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. */
|
/** Implement MDL_wait_for_subgraph interface. */
|
||||||
uint get_deadlock_weight() const;
|
virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor);
|
||||||
|
virtual uint get_deadlock_weight() const;
|
||||||
private:
|
private:
|
||||||
friend class MDL_context;
|
friend class MDL_context;
|
||||||
|
|
||||||
@ -462,7 +527,7 @@ public:
|
|||||||
enum_wait_status get_status();
|
enum_wait_status get_status();
|
||||||
void reset_status();
|
void reset_status();
|
||||||
enum_wait_status timed_wait(THD *thd, struct timespec *abs_timeout,
|
enum_wait_status timed_wait(THD *thd, struct timespec *abs_timeout,
|
||||||
bool signal_timeout);
|
bool signal_timeout, const char *wait_state_name);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Condvar which is used for waiting until this context's pending
|
Condvar which is used for waiting until this context's pending
|
||||||
@ -582,8 +647,6 @@ public:
|
|||||||
{
|
{
|
||||||
return m_needs_thr_lock_abort;
|
return m_needs_thr_lock_abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find_deadlock(Deadlock_detection_visitor *dvisitor);
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
If our request for a lock is scheduled, or aborted by the deadlock
|
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;
|
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
|
In principle, this is redundant, as information can be found
|
||||||
by inspecting waiting queues, but we'd very much like it to be
|
by inspecting waiting queues, but we'd very much like it to be
|
||||||
readily available to the wait-for graph iterator.
|
readily available to the wait-for graph iterator.
|
||||||
*/
|
*/
|
||||||
MDL_ticket *m_waiting_for;
|
MDL_wait_for_subgraph *m_waiting_for;
|
||||||
private:
|
private:
|
||||||
MDL_ticket *find_ticket(MDL_request *mdl_req,
|
MDL_ticket *find_ticket(MDL_request *mdl_req,
|
||||||
bool *is_transactional);
|
bool *is_transactional);
|
||||||
@ -688,13 +752,16 @@ private:
|
|||||||
bool try_acquire_lock_impl(MDL_request *mdl_request,
|
bool try_acquire_lock_impl(MDL_request *mdl_request,
|
||||||
MDL_ticket **out_ticket);
|
MDL_ticket **out_ticket);
|
||||||
|
|
||||||
|
public:
|
||||||
void find_deadlock();
|
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. */
|
/** 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);
|
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);
|
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,6 +772,14 @@ private:
|
|||||||
m_waiting_for= NULL;
|
m_waiting_for= NULL;
|
||||||
mysql_prlock_unlock(&m_LOCK_waiting_for);
|
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:
|
private:
|
||||||
MDL_context(const MDL_context &rhs); /* not implemented */
|
MDL_context(const MDL_context &rhs); /* not implemented */
|
||||||
MDL_context &operator=(MDL_context &rhs); /* not implemented */
|
MDL_context &operator=(MDL_context &rhs); /* not implemented */
|
||||||
|
@ -87,6 +87,7 @@
|
|||||||
#include <errmsg.h>
|
#include <errmsg.h>
|
||||||
#include "sp_rcontext.h"
|
#include "sp_rcontext.h"
|
||||||
#include "sp_cache.h"
|
#include "sp_cache.h"
|
||||||
|
#include "sql_reload.h" // reload_acl_and_cache
|
||||||
|
|
||||||
#ifdef HAVE_POLL_H
|
#ifdef HAVE_POLL_H
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@ -601,7 +602,7 @@ SHOW_COMP_OPTION have_profiling;
|
|||||||
pthread_key(MEM_ROOT**,THR_MALLOC);
|
pthread_key(MEM_ROOT**,THR_MALLOC);
|
||||||
pthread_key(THD*, THR_THD);
|
pthread_key(THD*, THR_THD);
|
||||||
mysql_mutex_t LOCK_thread_count;
|
mysql_mutex_t LOCK_thread_count;
|
||||||
mysql_mutex_t LOCK_open,
|
mysql_mutex_t
|
||||||
LOCK_status, LOCK_global_read_lock,
|
LOCK_status, LOCK_global_read_lock,
|
||||||
LOCK_error_log, LOCK_uuid_generator,
|
LOCK_error_log, LOCK_uuid_generator,
|
||||||
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
|
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_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
|
||||||
mysql_rwlock_t LOCK_system_variables_hash;
|
mysql_rwlock_t LOCK_system_variables_hash;
|
||||||
mysql_cond_t COND_thread_count;
|
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_t signal_thread;
|
||||||
pthread_attr_t connection_attrib;
|
pthread_attr_t connection_attrib;
|
||||||
mysql_mutex_t LOCK_server_started;
|
mysql_mutex_t LOCK_server_started;
|
||||||
@ -1526,7 +1527,6 @@ static void wait_for_signal_thread_to_end()
|
|||||||
static void clean_up_mutexes()
|
static void clean_up_mutexes()
|
||||||
{
|
{
|
||||||
mysql_rwlock_destroy(&LOCK_grant);
|
mysql_rwlock_destroy(&LOCK_grant);
|
||||||
mysql_mutex_destroy(&LOCK_open);
|
|
||||||
mysql_mutex_destroy(&LOCK_thread_count);
|
mysql_mutex_destroy(&LOCK_thread_count);
|
||||||
mysql_mutex_destroy(&LOCK_status);
|
mysql_mutex_destroy(&LOCK_status);
|
||||||
mysql_mutex_destroy(&LOCK_delayed_insert);
|
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_prepared_stmt_count);
|
||||||
mysql_mutex_destroy(&LOCK_error_messages);
|
mysql_mutex_destroy(&LOCK_error_messages);
|
||||||
mysql_cond_destroy(&COND_thread_count);
|
mysql_cond_destroy(&COND_thread_count);
|
||||||
mysql_cond_destroy(&COND_refresh);
|
|
||||||
mysql_cond_destroy(&COND_global_read_lock);
|
mysql_cond_destroy(&COND_global_read_lock);
|
||||||
mysql_cond_destroy(&COND_thread_cache);
|
mysql_cond_destroy(&COND_thread_cache);
|
||||||
mysql_cond_destroy(&COND_flush_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()
|
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_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_status, &LOCK_status, MY_MUTEX_INIT_FAST);
|
||||||
mysql_mutex_init(key_LOCK_delayed_insert,
|
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_sys_init_slave, &LOCK_sys_init_slave);
|
||||||
mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
|
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_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_global_read_lock, &COND_global_read_lock, NULL);
|
||||||
mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, 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);
|
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_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_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables,
|
||||||
key_LOCK_manager,
|
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_rpl_status, key_LOCK_server_started, key_LOCK_status,
|
||||||
key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
|
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,
|
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_read_lock, "LOCK_global_read_lock", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_global_system_variables, "LOCK_global_system_variables", 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_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_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_server_started, "LOCK_server_started", 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,
|
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_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_delayed_insert_cond, key_delayed_insert_cond_client,
|
||||||
key_item_func_sleep_cond, key_master_info_data_cond,
|
key_item_func_sleep_cond, key_master_info_data_cond,
|
||||||
key_master_info_start_cond, key_master_info_stop_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_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
|
||||||
{ &key_COND_global_read_lock, "COND_global_read_lock", PSI_FLAG_GLOBAL},
|
{ &key_COND_global_read_lock, "COND_global_read_lock", PSI_FLAG_GLOBAL},
|
||||||
{ &key_COND_manager, "COND_manager", 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_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL},
|
||||||
{ &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
|
{ &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
|
||||||
{ &key_delayed_insert_cond, "Delayed_insert::cond", 0},
|
{ &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_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_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables,
|
||||||
key_LOCK_logger, key_LOCK_manager,
|
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_rpl_status, key_LOCK_server_started, key_LOCK_status,
|
||||||
key_LOCK_table_share, key_LOCK_thd_data,
|
key_LOCK_table_share, key_LOCK_thd_data,
|
||||||
key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
|
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,
|
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_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_delayed_insert_cond, key_delayed_insert_cond_client,
|
||||||
key_item_func_sleep_cond, key_master_info_data_cond,
|
key_item_func_sleep_cond, key_master_info_data_cond,
|
||||||
key_master_info_start_cond, key_master_info_stop_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.
|
Server mutex locks and condition variables.
|
||||||
*/
|
*/
|
||||||
extern mysql_mutex_t LOCK_open,
|
extern mysql_mutex_t
|
||||||
LOCK_user_locks, LOCK_status,
|
LOCK_user_locks, LOCK_status,
|
||||||
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
||||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
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_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
|
||||||
extern mysql_rwlock_t LOCK_system_variables_hash;
|
extern mysql_rwlock_t LOCK_system_variables_hash;
|
||||||
extern mysql_cond_t COND_thread_count;
|
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 mysql_cond_t COND_global_read_lock;
|
||||||
extern int32 thread_running;
|
extern int32 thread_running;
|
||||||
extern my_atomic_rwlock_t thread_running_lock;
|
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);
|
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&LOCK_open);
|
||||||
if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
|
share= get_table_share(thd, table_list, key, key_length, 0,
|
||||||
&error, hash_value))))
|
&error, hash_value);
|
||||||
{
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
if (share == NULL)
|
||||||
DBUG_RETURN(0); // Can't open frm file
|
DBUG_RETURN(0); // Can't open frm file
|
||||||
}
|
|
||||||
|
|
||||||
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
|
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
|
||||||
{
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_open);
|
||||||
release_table_share(share);
|
release_table_share(share);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
DBUG_RETURN(0); // Out of memory
|
DBUG_RETURN(0); // Out of memory
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
table= &tmp_table;
|
table= &tmp_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,10 +771,8 @@ send_result_message:
|
|||||||
}
|
}
|
||||||
else if (open_for_modify || fatal_error)
|
else if (open_for_modify || fatal_error)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||||
table->db, table->table_name);
|
table->db, table->table_name, FALSE);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
/*
|
/*
|
||||||
May be something modified. Consequently, we have to
|
May be something modified. Consequently, we have to
|
||||||
invalidate the query cache.
|
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
|
#define RTFC_CHECK_KILLED_FLAG 0x0004
|
||||||
|
|
||||||
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
|
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
|
||||||
|
extern mysql_mutex_t LOCK_open;
|
||||||
bool table_cache_init(void);
|
bool table_cache_init(void);
|
||||||
void table_cache_free(void);
|
void table_cache_free(void);
|
||||||
bool table_def_init(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,
|
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||||
uint lock_flags);
|
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,
|
bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||||
Open_table_context *ot_ctx);
|
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,
|
bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||||
uint db_stat, uint prgflag,
|
uint db_stat, uint prgflag,
|
||||||
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
|
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);
|
ulong want_access);
|
||||||
bool wait_while_table_is_used(THD *thd, TABLE *table,
|
bool wait_while_table_is_used(THD *thd, TABLE *table,
|
||||||
enum ha_extra_function function);
|
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,
|
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||||
const char *table_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,
|
void update_non_unique_table_error(TABLE_LIST *update,
|
||||||
const char *operation,
|
const char *operation,
|
||||||
TABLE_LIST *duplicate);
|
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);
|
void close_temporary(TABLE *table, bool free_share, bool delete_table);
|
||||||
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
||||||
const char *table_name);
|
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);
|
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
||||||
|
|
||||||
/* Functions to work with system tables. */
|
/* 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);
|
Open_tables_state *backup);
|
||||||
void close_performance_schema_table(THD *thd, 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 close_cached_tables(THD *thd, TABLE_LIST *tables,
|
||||||
bool wait_for_refresh);
|
bool wait_for_refresh, ulong timeout);
|
||||||
bool close_cached_connection_tables(THD *thd, bool wait_for_refresh,
|
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
|
||||||
LEX_STRING *connect_string,
|
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||||
bool have_lock = FALSE);
|
bool remove_from_locked_tables);
|
||||||
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
|
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,
|
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,
|
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||||
char *cache_key, uint cache_key_length,
|
char *cache_key, uint cache_key_length,
|
||||||
MEM_ROOT *mem_root, uint flags);
|
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);
|
void mark_tmp_table_for_reuse(TABLE *table);
|
||||||
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
|
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
|
||||||
|
|
||||||
extern uint table_cache_count;
|
|
||||||
extern TABLE *unused_tables;
|
extern TABLE *unused_tables;
|
||||||
extern Item **not_found_item;
|
extern Item **not_found_item;
|
||||||
extern Field *not_found_field;
|
extern Field *not_found_field;
|
||||||
extern Field *view_ref_found;
|
extern Field *view_ref_found;
|
||||||
extern HASH open_cache;
|
|
||||||
extern HASH table_def_cache;
|
extern HASH table_def_cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -446,8 +469,8 @@ public:
|
|||||||
enum enum_open_table_action
|
enum enum_open_table_action
|
||||||
{
|
{
|
||||||
OT_NO_ACTION= 0,
|
OT_NO_ACTION= 0,
|
||||||
OT_MDL_CONFLICT,
|
OT_BACKOFF_AND_RETRY,
|
||||||
OT_WAIT_TDC,
|
OT_REOPEN_TABLES,
|
||||||
OT_DISCOVER,
|
OT_DISCOVER,
|
||||||
OT_REPAIR
|
OT_REPAIR
|
||||||
};
|
};
|
||||||
@ -457,9 +480,6 @@ public:
|
|||||||
bool request_backoff_action(enum_open_table_action action_arg,
|
bool request_backoff_action(enum_open_table_action action_arg,
|
||||||
TABLE_LIST *table);
|
TABLE_LIST *table);
|
||||||
|
|
||||||
void add_request(MDL_request *request)
|
|
||||||
{ m_mdl_requests.push_front(request); }
|
|
||||||
|
|
||||||
bool can_recover_from_failed_open() const
|
bool can_recover_from_failed_open() const
|
||||||
{ return m_action != OT_NO_ACTION; }
|
{ return m_action != OT_NO_ACTION; }
|
||||||
|
|
||||||
@ -481,8 +501,6 @@ public:
|
|||||||
|
|
||||||
uint get_flags() const { return m_flags; }
|
uint get_flags() const { return m_flags; }
|
||||||
private:
|
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
|
For OT_DISCOVER and OT_REPAIR actions, the table list element for
|
||||||
the table which definition should be re-discovered or which
|
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 */
|
#endif /* SQL_BASE_INCLUDED */
|
||||||
|
@ -934,7 +934,7 @@ void mysql_ha_flush(THD *thd)
|
|||||||
((hash_tables->table->mdl_ticket &&
|
((hash_tables->table->mdl_ticket &&
|
||||||
hash_tables->table->mdl_ticket->has_pending_conflicting_lock()) ||
|
hash_tables->table->mdl_ticket->has_pending_conflicting_lock()) ||
|
||||||
(!hash_tables->table->s->tmp_table &&
|
(!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);
|
mysql_ha_close_table(thd, hash_tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2705,7 +2705,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
|
|
||||||
thd_proc_info(&thd, "insert");
|
thd_proc_info(&thd, "insert");
|
||||||
max_rows= delayed_insert_limit;
|
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;
|
thd.killed= THD::KILL_CONNECTION;
|
||||||
max_rows= ULONG_MAX; // Do as much as possible
|
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))
|
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,
|
quick_rm_table(create_info->db_type, create_table->db,
|
||||||
table_case_name(create_info, create_table->table_name),
|
table_case_name(create_info, create_table->table_name),
|
||||||
0);
|
0);
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
table= create_table->table;
|
table= create_table->table;
|
||||||
|
393
sql/sql_parse.cc
393
sql/sql_parse.cc
@ -50,6 +50,7 @@
|
|||||||
// mysql_backup_table,
|
// mysql_backup_table,
|
||||||
// mysql_restore_table
|
// mysql_restore_table
|
||||||
#include "sql_truncate.h" // mysql_truncate_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_admin.h" // mysql_assign_to_keycache
|
||||||
#include "sql_connect.h" // check_user,
|
#include "sql_connect.h" // check_user,
|
||||||
// decrease_user_connections,
|
// 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.
|
Read query from packet and store in thd->query.
|
||||||
Used in COM_QUERY and COM_STMT_PREPARE.
|
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 */
|
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
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,
|
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
|
||||||
lex->drop_temporary);
|
lex->drop_temporary);
|
||||||
}
|
}
|
||||||
@ -3771,6 +3638,10 @@ end_with_restore_list:
|
|||||||
|
|
||||||
if (first_table && lex->type & REFRESH_READ_LOCK)
|
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))
|
if (flush_tables_with_read_lock(thd, all_tables))
|
||||||
goto error;
|
goto error;
|
||||||
my_ok(thd);
|
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.
|
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);
|
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
|
||||||
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
||||||
pthread_handler_t handle_bootstrap(void *arg);
|
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);
|
int mysql_execute_command(THD *thd);
|
||||||
bool do_command(THD *thd);
|
bool do_command(THD *thd);
|
||||||
void do_handle_bootstrap(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,
|
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||||
table->s->db.str,
|
table->s->db.str,
|
||||||
table->s->table_name.str);
|
table->s->table_name.str, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
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;
|
READ_RECORD read_record_info;
|
||||||
int error;
|
int error;
|
||||||
THD *new_thd= &thd;
|
THD *new_thd= &thd;
|
||||||
|
bool result;
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
bool table_exists;
|
No_such_table_error_handler error_handler;
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
DBUG_ENTER("plugin_load");
|
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
|
When building an embedded library, if the mysql.plugin table
|
||||||
does not exist, we silently ignore the missing table
|
does not exist, we silently ignore the missing table
|
||||||
*/
|
*/
|
||||||
if (check_if_table_exists(new_thd, &tables, &table_exists))
|
new_thd->push_internal_handler(&error_handler);
|
||||||
table_exists= FALSE;
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
if (!table_exists)
|
|
||||||
|
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;
|
goto end;
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#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"));
|
DBUG_PRINT("error",("Can't open plugin table"));
|
||||||
sql_print_error("Can't open the mysql.plugin table. Please "
|
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))
|
MYSQL_OPEN_SKIP_TEMPORARY))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
|
|
||||||
for (ren_table= table_list; ren_table; ren_table= ren_table->next_local)
|
for (ren_table= table_list; ren_table; ren_table= ren_table->next_local)
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, ren_table->db,
|
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, ren_table->db,
|
||||||
ren_table->table_name);
|
ren_table->table_name, FALSE);
|
||||||
|
|
||||||
error=0;
|
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)))
|
if ((ren_table=rename_tables(thd,table_list,0)))
|
||||||
{
|
{
|
||||||
/* Rename didn't succeed; rename back the tables in reverse order */
|
/* 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;
|
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)
|
if (!silent && !error)
|
||||||
{
|
{
|
||||||
@ -197,8 +188,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
|||||||
if (!error)
|
if (!error)
|
||||||
query_cache_invalidate3(thd, table_list, 0);
|
query_cache_invalidate3(thd, table_list, 0);
|
||||||
|
|
||||||
thd->mdl_context.release_transactional_locks();
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
thd->global_read_lock.start_waiting_global_read_lock(thd);
|
thd->global_read_lock.start_waiting_global_read_lock(thd);
|
||||||
DBUG_RETURN(error || binlog_error);
|
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 the servers table before we call closed_cached_connection_tables */
|
||||||
close_mysql_tables(thd);
|
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,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_UNKNOWN_ERROR, "Server connection in use");
|
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 the servers table before we call closed_cached_connection_tables */
|
||||||
close_mysql_tables(thd);
|
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,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_UNKNOWN_ERROR, "Server connection in use");
|
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
|
TODO: investigate if in this particular situation we can get by
|
||||||
simply obtaining internal lock of data-dictionary (ATM it
|
simply obtaining internal lock of the data-dictionary
|
||||||
is LOCK_open) instead of obtaning full-blown metadata lock.
|
instead of obtaining full-blown metadata lock.
|
||||||
*/
|
*/
|
||||||
if (try_acquire_high_prio_shared_mdl_lock(thd, &table_list, can_deadlock))
|
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
|
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];
|
char trn_path_buff[FN_REFLEN];
|
||||||
LEX_STRING trn_path= { trn_path_buff, 0 };
|
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;
|
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.
|
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
|
completing this we write a new phase to the log entry that will
|
||||||
deactivate it.
|
deactivate it.
|
||||||
*/
|
*/
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)) ||
|
if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)) ||
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
lpt->table->file->ha_create_handler_files(path, shadow_path,
|
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
|
#endif
|
||||||
|
|
||||||
err:
|
err:
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
|
deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
|
||||||
part_info->frm_log_entry= NULL;
|
part_info->frm_log_entry= NULL;
|
||||||
(void) sync_ddl_log();
|
(void) sync_ddl_log();
|
||||||
#endif
|
#endif
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
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,
|
if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout,
|
||||||
MYSQL_OPEN_SKIP_TEMPORARY))
|
MYSQL_OPEN_SKIP_TEMPORARY))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
for (table= tables; table; table= table->next_local)
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -2171,15 +2171,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
built_query.append("`,");
|
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");
|
DEBUG_SYNC(thd, "rm_table_part2_before_delete_table");
|
||||||
DBUG_EXECUTE_IF("sleep_before_part2_delete_table",
|
DBUG_EXECUTE_IF("sleep_before_part2_delete_table",
|
||||||
my_sleep(100000););
|
my_sleep(100000););
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
error= 0;
|
error= 0;
|
||||||
if (drop_temporary ||
|
if (drop_temporary ||
|
||||||
((access(path, F_OK) &&
|
((access(path, F_OK) &&
|
||||||
@ -2209,8 +2203,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
char *end;
|
char *end;
|
||||||
/*
|
/*
|
||||||
Cannot use the db_type from the table, since that might have changed
|
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,
|
while waiting for the exclusive name lock.
|
||||||
so reading from the frm-file is safe.
|
|
||||||
*/
|
*/
|
||||||
if (frm_db_type == DB_TYPE_UNKNOWN)
|
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;
|
non_tmp_error= error ? TRUE : non_tmp_error;
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (wrong_tables.length())
|
if (wrong_tables.length())
|
||||||
@ -4098,7 +4090,6 @@ bool mysql_create_table_no_lock(THD *thd,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||||
{
|
{
|
||||||
if (!access(path,F_OK))
|
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)
|
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
||||||
goto warn;
|
goto warn;
|
||||||
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
|
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
|
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
|
Then she could create the table. This case is pretty obscure and
|
||||||
therefore we don't introduce a new error message only for it.
|
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))
|
if (get_cached_table_share(db, table_name))
|
||||||
{
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
|
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
|
exist in any storage engine. In such a case it should
|
||||||
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
|
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
|
||||||
unless user specified CREATE TABLE IF EXISTS
|
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
|
one else is attempting to discover the table. Since
|
||||||
it's not on disk as a frm file, no one could be using it!
|
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)
|
if (create_if_not_exists)
|
||||||
goto warn;
|
goto warn;
|
||||||
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
|
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
|
DBUG_PRINT("info", ("error: %u from storage engine", retcode));
|
||||||
my_error(retcode, MYF(0),table_name);
|
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))
|
if (test_if_data_home_dir(dirpath))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
|
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (create_info->index_file_name)
|
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))
|
if (test_if_data_home_dir(dirpath))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
|
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
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
if (check_partition_dirs(thd->lex->part_info))
|
if (check_partition_dirs(thd->lex->part_info))
|
||||||
{
|
{
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
#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,
|
if (rea_create_table(thd, path, db, table_name,
|
||||||
create_info, alter_info->create_list,
|
create_info, alter_info->create_list,
|
||||||
key_count, key_info_buffer, file))
|
key_count, key_info_buffer, file))
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
|
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
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)))
|
if (!(table= open_temporary_table(thd, path, db, table_name, 1)))
|
||||||
{
|
{
|
||||||
(void) rm_temporary_table(create_info->db_type, path);
|
(void) rm_temporary_table(create_info->db_type, path);
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_trans != NULL)
|
if (is_trans != NULL)
|
||||||
@ -4245,9 +4239,6 @@ bool mysql_create_table_no_lock(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
unlock_and_end:
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
thd_proc_info(thd, "After create");
|
thd_proc_info(thd, "After create");
|
||||||
delete file;
|
delete file;
|
||||||
@ -4258,7 +4249,7 @@ warn:
|
|||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
|
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
|
||||||
alias);
|
alias);
|
||||||
goto unlock_and_end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5920,7 +5911,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
*fn_ext(new_name)=0;
|
*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))
|
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
|
||||||
error= -1;
|
error= -1;
|
||||||
else if (Table_triggers_list::change_table_name(thd, db, table_name,
|
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);
|
table_name, 0);
|
||||||
error= -1;
|
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. */
|
/* This type cannot happen in regular ALTER. */
|
||||||
new_db_type= old_db_type= NULL;
|
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,
|
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
|
||||||
FN_TO_IS_TMP))
|
FN_TO_IS_TMP))
|
||||||
{
|
{
|
||||||
@ -6576,8 +6564,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
if (! error)
|
if (! error)
|
||||||
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
||||||
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
/* This shouldn't happen. But let us play it safe. */
|
/* 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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ static void print_cached_tables(void)
|
|||||||
printf("unused_links isn't linked properly\n");
|
printf("unused_links isn't linked properly\n");
|
||||||
return;
|
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)
|
if (lnk != start_link)
|
||||||
{
|
{
|
||||||
printf("Unused_links aren't connected\n");
|
printf("Unused_links aren't connected\n");
|
||||||
@ -416,7 +416,7 @@ static void display_table_locks(void)
|
|||||||
void *saved_base;
|
void *saved_base;
|
||||||
DYNAMIC_ARRAY saved_table_locks;
|
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);
|
mysql_mutex_lock(&THR_LOCK_lock);
|
||||||
for (list= thr_lock_thread_list; list; list= list_rest(list))
|
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
|
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
|
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
|
again until we are done, unless we are under lock tables.
|
||||||
LOCK_open is not enough because global read lock is held without holding
|
|
||||||
LOCK_open).
|
|
||||||
*/
|
*/
|
||||||
if (!thd->locked_tables_mode &&
|
if (!thd->locked_tables_mode &&
|
||||||
thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
|
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;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
|
||||||
result= (create ?
|
result= (create ?
|
||||||
table->triggers->create_trigger(thd, tables, &stmt_query):
|
table->triggers->create_trigger(thd, tables, &stmt_query):
|
||||||
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
goto end;
|
||||||
@ -1680,9 +1676,6 @@ bool add_table_for_trigger(THD *thd,
|
|||||||
@param db schema for table
|
@param db schema for table
|
||||||
@param name name for table
|
@param name name for table
|
||||||
|
|
||||||
@note
|
|
||||||
The calling thread should hold the LOCK_open mutex;
|
|
||||||
|
|
||||||
@retval
|
@retval
|
||||||
False success
|
False success
|
||||||
@retval
|
@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
|
This method interfaces the mysql server code protected by
|
||||||
either LOCK_open mutex or with an exclusive metadata lock.
|
an exclusive metadata lock.
|
||||||
In the future, only an exclusive metadata lock will be enough.
|
|
||||||
*/
|
*/
|
||||||
#ifndef DBUG_OFF
|
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, old_table,
|
||||||
if (thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, old_table,
|
MDL_EXCLUSIVE));
|
||||||
MDL_EXCLUSIVE))
|
|
||||||
mysql_mutex_assert_owner(&LOCK_open);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
||||||
my_strcasecmp(table_alias_charset, old_table, new_table));
|
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