mysql lock scene and investigation

1, the query does not return for a long time:

Execute the following SQL statement in Table t:

mysql> select * from t where id=1;

Query results for a long time do not return.

Generally encountered such a situation, it is a big probability table t is locked. Next Analysis of reasons, usually performed first at show processlist command to see what state the current statement. Then we for each state, to analyze their causes, how to reproduce, and how to handle. MDL other lock shown below, is to use show processlist command schematic view of Waiting for table metadata lock.

 

Represents the emergence of this state, there is a thread table holds MDL request or write lock on t, the select statement is blocked.

However, in MySQL 5.7 version reproduce this scene, it is also very easy. As shown in FIG. 3, I give a simple reproduction step.

 

 session A write lock held by t MDL table lock table command, query and session B of MDL need to get a read lock. Therefore, session B enters a waiting state. Way to deal with such problems is to find someone who holds MDL write lock, then kill it off. However, since the inside of the results show processlist, Command column session A is "Sleep", resulting in very easy to find. But later with performance_schema sys and system libraries, much more convenient. (Need to set performance_schema = on MySQL is started, compared to set off there will be a performance penalty of about 10%) by querying sys.schema_table_lock_waits this table, we can find out the process id directly causing obstruction, this connection kill command to disconnect.

 

 2, such as row locks:

Now, after a table-level lock test, we finally came to the select statement in the engine.

mysql> select * from t where id=1 lock in share mode; 

Because access id = 1 this record to add a read lock, if this time there is already a transaction holds a write lock on the record this line, we select statement will be blocked. Steps to reproduce and live as follows:

 

command to view the show processlist

 

 

 Obviously, session A started a transaction, possession write locks, do not submit, it is the cause of session B is blocked. The problem is not difficult to analyze, but the question is how to find out who occupied the write lock. If you are using a version of MySQL 5.7, you can be found by sys.innodb_lock_waits table. Query method is:

mysql> select * from t sys.innodb_lock_waits where locked_table=`'test'.'t'`\G

 

可以看到,这个信息很全,4 号线程是造成堵塞的罪魁祸首。而干掉这个罪魁祸首的方式,就是 KILL QUERY 4 或 KILL 4。不过,这里不应该显示“KILL QUERY 4”。这个命令表示停止 4 号线程当前正在执行的语句,而这个方法其实是没有用的。因为占有行锁的是 update 语句,这个语句已经是之前执行完成了的,现在执行 KILL QUERY,无法让这个事务去掉 id=1 上的行锁。实际上,KILL 4 才有效,也就是说直接断开这个连接。这里隐含的一个逻辑就是,连接被断开的时候,会自动回滚这个连接里面正在执行的线程,也就释放了 id=1 上的行锁。

 

PS:

select * from information_schema.innodb_trx 或者 select * from information_schema.innodb_trx\G;

其中字段解释如下:

  • trx_state: 事务状态,一般为RUNNING
  • trx_started: 事务执行的起始时间,若时间较长,则要分析该事务是否合理
  • trx_mysql_thread_id: MySQL的线程ID,用于kill
  • trx_query: 事务中的sql

Guess you like

Origin www.cnblogs.com/Joy-Hu/p/12221705.html