add metadata_lock_info
This commit is contained in:
parent
1f9d4819ad
commit
3771e14ea9
2
plugin/metadata_lock_info/CMakeLists.txt
Normal file
2
plugin/metadata_lock_info/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
SET(METADATA_LOCK_INFO_SOURCES metadata_lock_info.cc)
|
||||
MYSQL_ADD_PLUGIN(metadata_lock_info ${METADATA_LOCK_INFO_SOURCES} MODULE_OUTPUT_NAME "metadata_lock_info")
|
188
plugin/metadata_lock_info/metadata_lock_info.cc
Normal file
188
plugin/metadata_lock_info/metadata_lock_info.cc
Normal file
@ -0,0 +1,188 @@
|
||||
/* Copyright (C) 2013 Kentoku Shiba
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#define MYSQL_SERVER 1
|
||||
#include "mysql_version.h"
|
||||
#include "mysql/plugin.h"
|
||||
#include "sql_class.h"
|
||||
#include "sql_show.h"
|
||||
|
||||
static const LEX_STRING metadata_lock_info_lock_name[] = {
|
||||
{ C_STRING_WITH_LEN("Global read lock") },
|
||||
{ C_STRING_WITH_LEN("Schema metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Table metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Stored function metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Stored procedure metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Trigger metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Event metadata lock") },
|
||||
{ C_STRING_WITH_LEN("Commit lock") },
|
||||
{ C_STRING_WITH_LEN("User lock") },
|
||||
};
|
||||
|
||||
static const LEX_STRING metadata_lock_info_lock_mode[] = {
|
||||
{ C_STRING_WITH_LEN("MDL_INTENTION_EXCLUSIVE") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED_HIGH_PRIO") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED_READ") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED_WRITE") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED_NO_WRITE") },
|
||||
{ C_STRING_WITH_LEN("MDL_SHARED_NO_READ_WRITE") },
|
||||
{ C_STRING_WITH_LEN("MDL_EXCLUSIVE") },
|
||||
};
|
||||
|
||||
static const LEX_STRING metadata_lock_info_duration[] = {
|
||||
{ C_STRING_WITH_LEN("MDL_STATEMENT") },
|
||||
{ C_STRING_WITH_LEN("MDL_TRANSACTION") },
|
||||
{ C_STRING_WITH_LEN("MDL_EXPLICIT") },
|
||||
};
|
||||
|
||||
static ST_FIELD_INFO i_s_metadata_lock_info_fields_info[] =
|
||||
{
|
||||
{"THREAD_ID", 20, MYSQL_TYPE_LONGLONG, 0,
|
||||
MY_I_S_UNSIGNED, "thread_id", SKIP_OPEN_TABLE},
|
||||
{"LOCK_MODE", 24, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, "lock_mode", SKIP_OPEN_TABLE},
|
||||
{"LOCK_DURATION", 30, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, "lock_duration", SKIP_OPEN_TABLE},
|
||||
{"LOCK_TYPE", 30, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, "lock_type", SKIP_OPEN_TABLE},
|
||||
{"TABLE_SCHEMA", 64, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, "table_schema", SKIP_OPEN_TABLE},
|
||||
{"TABLE_NAME", 64, MYSQL_TYPE_STRING, 0,
|
||||
MY_I_S_MAYBE_NULL, "table_name", SKIP_OPEN_TABLE},
|
||||
{NULL, 0, MYSQL_TYPE_STRING, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
struct st_i_s_metadata_param
|
||||
{
|
||||
THD *thd;
|
||||
TABLE *table;
|
||||
};
|
||||
|
||||
int i_s_metadata_lock_info_fill_row(
|
||||
MDL_ticket *mdl_ticket,
|
||||
void *arg
|
||||
) {
|
||||
st_i_s_metadata_param *param = (st_i_s_metadata_param *) arg;
|
||||
THD *thd = param->thd;
|
||||
TABLE *table = param->table;
|
||||
DBUG_ENTER("i_s_metadata_lock_info_fill_row");
|
||||
MDL_request mdl_request;
|
||||
enum_mdl_duration mdl_duration;
|
||||
MDL_context *mdl_ctx = mdl_ticket->get_ctx();
|
||||
enum_mdl_type mdl_ticket_type = mdl_ticket->get_type();
|
||||
MDL_key *mdl_key = mdl_ticket->get_key();
|
||||
MDL_key::enum_mdl_namespace mdl_namespace = mdl_key->mdl_namespace();
|
||||
mdl_request.init(mdl_key, mdl_ticket_type, MDL_STATEMENT);
|
||||
mdl_ctx->find_ticket(&mdl_request, &mdl_duration);
|
||||
table->field[0]->store((longlong) mdl_ctx->get_thread_id(), TRUE);
|
||||
table->field[1]->set_notnull();
|
||||
table->field[1]->store(
|
||||
metadata_lock_info_lock_mode[(int) mdl_ticket_type].str,
|
||||
metadata_lock_info_lock_mode[(int) mdl_ticket_type].length,
|
||||
system_charset_info);
|
||||
table->field[2]->set_notnull();
|
||||
table->field[2]->store(
|
||||
metadata_lock_info_duration[(int) mdl_duration].str,
|
||||
metadata_lock_info_duration[(int) mdl_duration].length,
|
||||
system_charset_info);
|
||||
table->field[3]->set_notnull();
|
||||
table->field[3]->store(
|
||||
metadata_lock_info_lock_name[(int) mdl_namespace].str,
|
||||
metadata_lock_info_lock_name[(int) mdl_namespace].length,
|
||||
system_charset_info);
|
||||
table->field[4]->set_notnull();
|
||||
table->field[4]->store(mdl_key->db_name(),
|
||||
mdl_key->db_name_length(), system_charset_info);
|
||||
table->field[5]->set_notnull();
|
||||
table->field[5]->store(mdl_key->name(),
|
||||
mdl_key->name_length(), system_charset_info);
|
||||
if (schema_table_store_record(thd, table))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int i_s_metadata_lock_info_fill_table(
|
||||
THD *thd,
|
||||
TABLE_LIST *tables,
|
||||
COND *cond
|
||||
) {
|
||||
st_i_s_metadata_param param;
|
||||
DBUG_ENTER("i_s_metadata_lock_info_fill_table");
|
||||
param.table = tables->table;
|
||||
param.thd = thd;
|
||||
DBUG_RETURN(mdl_iterate(i_s_metadata_lock_info_fill_row, ¶m));
|
||||
}
|
||||
|
||||
static int i_s_metadata_lock_info_init(
|
||||
void *p
|
||||
) {
|
||||
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *) p;
|
||||
DBUG_ENTER("i_s_metadata_lock_info_init");
|
||||
schema->fields_info = i_s_metadata_lock_info_fields_info;
|
||||
schema->fill_table = i_s_metadata_lock_info_fill_table;
|
||||
schema->idx_field1 = 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static int i_s_metadata_lock_info_deinit(
|
||||
void *p
|
||||
) {
|
||||
DBUG_ENTER("i_s_metadata_lock_info_deinit");
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static struct st_mysql_information_schema i_s_metadata_lock_info_plugin =
|
||||
{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
|
||||
|
||||
#ifdef MARIADB_BASE_VERSION
|
||||
maria_declare_plugin(metadata_lock_info)
|
||||
{
|
||||
MYSQL_INFORMATION_SCHEMA_PLUGIN,
|
||||
&i_s_metadata_lock_info_plugin,
|
||||
"METADATA_LOCK_INFO",
|
||||
"Kentoku Shiba",
|
||||
"Metadata locking viewer",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
i_s_metadata_lock_info_init,
|
||||
i_s_metadata_lock_info_deinit,
|
||||
0x0001,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
MariaDB_PLUGIN_MATURITY_ALPHA,
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
#else
|
||||
mysql_declare_plugin(metadata_lock_info)
|
||||
{
|
||||
MYSQL_INFORMATION_SCHEMA_PLUGIN,
|
||||
&i_s_metadata_lock_info_plugin,
|
||||
"METADATA_LOCK_INFO",
|
||||
"Kentoku Shiba",
|
||||
"Metadata locking viewer",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
i_s_metadata_lock_info_init,
|
||||
i_s_metadata_lock_info_deinit,
|
||||
0x0001,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#if MYSQL_VERSION_ID >= 50600
|
||||
0,
|
||||
#endif
|
||||
}
|
||||
mysql_declare_plugin_end;
|
||||
#endif
|
@ -0,0 +1,10 @@
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
MDL_SHARED MDL_EXPLICIT Global read lock
|
||||
MDL_SHARED MDL_EXPLICIT Commit lock
|
||||
UNLOCK TABLES;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
@ -0,0 +1,13 @@
|
||||
CREATE TABLE IF NOT EXISTS t1(a int);
|
||||
BEGIN;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
MDL_SHARED_READ MDL_TRANSACTION Table metadata lock test t1
|
||||
ROLLBACK;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
DROP TABLE t1;
|
@ -0,0 +1,13 @@
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
SELECT GET_LOCK('LOCK1',0);
|
||||
GET_LOCK('LOCK1',0)
|
||||
1
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
||||
MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT User lock LOCK1
|
||||
SELECT RELEASE_LOCK('LOCK1');
|
||||
RELEASE_LOCK('LOCK1')
|
||||
1
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
lock_mode lock_duration lock_type table_schema table_name
|
@ -0,0 +1,2 @@
|
||||
--loose-metadata_lock_info
|
||||
--plugin-load=$METADATA_LOCK_INFO_SO
|
@ -0,0 +1,8 @@
|
||||
package My::Suite::Metadata_lock_info;
|
||||
|
||||
@ISA = qw(My::Suite);
|
||||
|
||||
return "No Metadata_lock_info plugin" unless $ENV{METADATA_LOCK_INFO_SO};
|
||||
|
||||
bless { };
|
||||
|
@ -0,0 +1,5 @@
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
UNLOCK TABLES;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
@ -0,0 +1,8 @@
|
||||
CREATE TABLE IF NOT EXISTS t1(a int);
|
||||
BEGIN;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
SELECT * FROM t1;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
ROLLBACK;
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
DROP TABLE t1;
|
@ -0,0 +1,5 @@
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
SELECT GET_LOCK('LOCK1',0);
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
||||
SELECT RELEASE_LOCK('LOCK1');
|
||||
SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info;
|
42
sql/mdl.cc
42
sql/mdl.cc
@ -158,6 +158,7 @@ private:
|
||||
I_P_List_counter>
|
||||
Lock_cache;
|
||||
Lock_cache m_unused_locks_cache;
|
||||
friend int mdl_iterate(int (*)(MDL_ticket *, void *), void *);
|
||||
};
|
||||
|
||||
|
||||
@ -187,6 +188,7 @@ private:
|
||||
MDL_lock *m_global_lock;
|
||||
/** Pre-allocated MDL_lock object for COMMIT namespace. */
|
||||
MDL_lock *m_commit_lock;
|
||||
friend int mdl_iterate(int (*)(MDL_ticket *, void *), void *);
|
||||
};
|
||||
|
||||
|
||||
@ -706,6 +708,46 @@ void mdl_destroy()
|
||||
}
|
||||
|
||||
|
||||
static inline int mdl_iterate_lock(MDL_lock *lock,
|
||||
int (*callback)(MDL_ticket *ticket, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
MDL_lock::Ticket_iterator ticket_it(lock->m_granted);
|
||||
MDL_ticket *ticket;
|
||||
int res= 0;
|
||||
mysql_prlock_rdlock(&lock->m_rwlock);
|
||||
while ((ticket= ticket_it++) && !(res= callback(ticket, arg))) /* no-op */;
|
||||
mysql_prlock_unlock(&lock->m_rwlock);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg)
|
||||
{
|
||||
uint i, j;
|
||||
int res;
|
||||
DBUG_ENTER("mdl_iterate");
|
||||
|
||||
if ((res= mdl_iterate_lock(mdl_locks.m_global_lock, callback, arg)) ||
|
||||
(res= mdl_iterate_lock(mdl_locks.m_commit_lock, callback, arg)))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
for (i= 0; i < mdl_locks.m_partitions.elements(); i++)
|
||||
{
|
||||
MDL_map_partition *part= mdl_locks.m_partitions.at(i);
|
||||
mysql_mutex_lock(&part->m_mutex);
|
||||
for (j= 0; j < part->m_locks.records; j++)
|
||||
{
|
||||
if ((res= mdl_iterate_lock((MDL_lock*) my_hash_element(&part->m_locks, j),
|
||||
callback, arg)))
|
||||
break;
|
||||
}
|
||||
mysql_mutex_unlock(&part->m_mutex);
|
||||
}
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
/** Initialize the container for all MDL locks. */
|
||||
|
||||
void MDL_map::init()
|
||||
|
@ -904,14 +904,14 @@ private:
|
||||
MDL_wait_for_subgraph *m_waiting_for;
|
||||
private:
|
||||
THD *get_thd() const { return m_owner->get_thd(); }
|
||||
MDL_ticket *find_ticket(MDL_request *mdl_req,
|
||||
enum_mdl_duration *duration);
|
||||
void release_locks_stored_before(enum_mdl_duration duration, MDL_ticket *sentinel);
|
||||
void release_lock(enum_mdl_duration duration, MDL_ticket *ticket);
|
||||
bool try_acquire_lock_impl(MDL_request *mdl_request,
|
||||
MDL_ticket **out_ticket);
|
||||
|
||||
public:
|
||||
MDL_ticket *find_ticket(MDL_request *mdl_req,
|
||||
enum_mdl_duration *duration);
|
||||
void find_deadlock();
|
||||
|
||||
ulong get_thread_id() const { return thd_get_thread_id(get_thd()); }
|
||||
@ -988,4 +988,7 @@ static const ulong MDL_LOCKS_HASH_PARTITIONS_DEFAULT = 8;
|
||||
to avoid starving out weak, low-prio locks.
|
||||
*/
|
||||
extern "C" ulong max_write_lock_count;
|
||||
|
||||
extern MYSQL_PLUGIN_IMPORT
|
||||
int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user