Commit d89cac08 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-28567 MDL debug logging

Log MDL state transitions. Trace-friendly message
format. DBUG_LOCK_FILE replaced by thread-local storage.

Logged states legend:
  Seized   lock was acquired without waiting
  Waiting  lock is waiting
  Acquired lock was acquired after waiting
  Released lock was released
  Deadlock lock was aborted due to deadlock
  Timeout  lock was aborted due to timeout >0
  Nowait   lock was aborted due to zero timeout
  Killed   lock was aborted due to kill message
  OOM	   can not acquire because out of memory

Usage:
  mtr --mysqld=--debug=d,mdl,query:i:o,/tmp/mdl.log

Cleanup from garbage messages:
  sed -i -re \
  '/(mysql|performance_schema|sys|mtr)\// d; /MDL_BACKUP_/ d' \
  /tmp/mdl.log
parent dbd56278
...@@ -230,25 +230,32 @@ class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor ...@@ -230,25 +230,32 @@ class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor
Print a list of all locks to DBUG trace to help with debugging Print a list of all locks to DBUG trace to help with debugging
*/ */
const char *dbug_print_mdl(MDL_ticket *mdl_ticket)
{
thread_local char buffer[256];
MDL_key *mdl_key= mdl_ticket->get_key();
my_snprintf(buffer, sizeof(buffer) - 1, "%.*s/%.*s (%s)",
(int) mdl_key->db_name_length(), mdl_key->db_name(),
(int) mdl_key->name_length(), mdl_key->name(),
mdl_ticket->get_type_name()->str);
return buffer;
}
static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted) static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted)
{ {
String *tmp= (String*) arg; String *tmp= (String*) arg;
char buffer[128]; char buffer[256];
MDL_key *mdl_key= mdl_ticket->get_key(); size_t length= my_snprintf(buffer, sizeof(buffer) - 1,
size_t length; "\n %s (%s)", dbug_print_mdl(mdl_ticket),
length= my_snprintf(buffer, sizeof(buffer)-1, granted ? "granted" : "waiting");
"\nname: %s db: %.*s key_name: %.*s (%s)",
mdl_ticket->get_type_name()->str,
(int) mdl_key->db_name_length(), mdl_key->db_name(),
(int) mdl_key->name_length(), mdl_key->name(),
granted ? "granted" : "waiting");
tmp->append(buffer, length); tmp->append(buffer, length);
return 0; return 0;
} }
const char *mdl_dbug_print_locks() const char *mdl_dbug_print_locks()
{ {
static String tmp; thread_local String tmp;
mdl_iterate(mdl_dbug_print_lock, (void*) &tmp); mdl_iterate(mdl_dbug_print_lock, (void*) &tmp);
return tmp.c_ptr(); return tmp.c_ptr();
} }
...@@ -2268,13 +2275,19 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2268,13 +2275,19 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
MDL_ticket *ticket; MDL_ticket *ticket;
MDL_wait::enum_wait_status wait_status; MDL_wait::enum_wait_status wait_status;
DBUG_ENTER("MDL_context::acquire_lock"); DBUG_ENTER("MDL_context::acquire_lock");
#ifndef DBUG_OFF
const char *mdl_lock_name= get_mdl_lock_name(
mdl_request->key.mdl_namespace(), mdl_request->type)->str;
#endif
DBUG_PRINT("enter", ("lock_type: %s timeout: %f", DBUG_PRINT("enter", ("lock_type: %s timeout: %f",
get_mdl_lock_name(mdl_request->key.mdl_namespace(), mdl_lock_name,
mdl_request->type)->str,
lock_wait_timeout)); lock_wait_timeout));
if (try_acquire_lock_impl(mdl_request, &ticket)) if (try_acquire_lock_impl(mdl_request, &ticket))
{
DBUG_PRINT("mdl", ("OOM: %s", mdl_lock_name));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
}
if (mdl_request->ticket) if (mdl_request->ticket)
{ {
...@@ -2284,9 +2297,14 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2284,9 +2297,14 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
accordingly, so we can simply return success. accordingly, so we can simply return success.
*/ */
DBUG_PRINT("info", ("Got lock without waiting")); DBUG_PRINT("info", ("Got lock without waiting"));
DBUG_PRINT("mdl", ("Seized: %s", dbug_print_mdl(mdl_request->ticket)));
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
#ifndef DBUG_OFF
const char *ticket_msg= dbug_print_mdl(ticket);
#endif
/* /*
Our attempt to acquire lock without waiting has failed. Our attempt to acquire lock without waiting has failed.
As a result of this attempt we got MDL_ticket with m_lock As a result of this attempt we got MDL_ticket with m_lock
...@@ -2297,6 +2315,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2297,6 +2315,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
if (lock_wait_timeout == 0) if (lock_wait_timeout == 0)
{ {
DBUG_PRINT("mdl", ("Nowait: %s", ticket_msg));
mysql_prlock_unlock(&lock->m_rwlock); mysql_prlock_unlock(&lock->m_rwlock);
MDL_ticket::destroy(ticket); MDL_ticket::destroy(ticket);
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
...@@ -2335,6 +2354,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2335,6 +2354,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
mysql_prlock_unlock(&lock->m_rwlock); mysql_prlock_unlock(&lock->m_rwlock);
DBUG_PRINT("mdl", ("Waiting: %s", ticket_msg));
will_wait_for(ticket); will_wait_for(ticket);
/* There is a shared or exclusive lock on the object. */ /* There is a shared or exclusive lock on the object. */
...@@ -2387,15 +2407,16 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2387,15 +2407,16 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
switch (wait_status) switch (wait_status)
{ {
case MDL_wait::VICTIM: case MDL_wait::VICTIM:
DBUG_LOCK_FILE; DBUG_PRINT("mdl", ("Deadlock: %s", ticket_msg));
DBUG_PRINT("mdl_locks", ("%s", mdl_dbug_print_locks())); DBUG_PRINT("mdl_locks", ("Existing locks:%s", mdl_dbug_print_locks()));
DBUG_UNLOCK_FILE;
my_error(ER_LOCK_DEADLOCK, MYF(0)); my_error(ER_LOCK_DEADLOCK, MYF(0));
break; break;
case MDL_wait::TIMEOUT: case MDL_wait::TIMEOUT:
DBUG_PRINT("mdl", ("Timeout: %s", ticket_msg));
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
break; break;
case MDL_wait::KILLED: case MDL_wait::KILLED:
DBUG_PRINT("mdl", ("Killed: %s", ticket_msg));
get_thd()->send_kill_message(); get_thd()->send_kill_message();
break; break;
default: default:
...@@ -2417,6 +2438,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) ...@@ -2417,6 +2438,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
mdl_request->ticket= ticket; mdl_request->ticket= ticket;
DBUG_PRINT("mdl", ("Acquired: %s", ticket_msg));
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
...@@ -2845,6 +2867,7 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket) ...@@ -2845,6 +2867,7 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket)
lock->key.db_name(), lock->key.name())); lock->key.db_name(), lock->key.name()));
DBUG_ASSERT(this == ticket->get_ctx()); DBUG_ASSERT(this == ticket->get_ctx());
DBUG_PRINT("mdl", ("Released: %s", dbug_print_mdl(ticket)));
lock->remove_ticket(m_pins, &MDL_lock::m_granted, ticket); lock->remove_ticket(m_pins, &MDL_lock::m_granted, ticket);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment