MySQL 死锁检查处理

正常情况下,死锁发生时,权重最小的连接将被kill并回滚。但是为了找出语句来优化,启用可启用死锁将死锁信息记录下来。

#step 1:窗口一
mysql> start transaction;
mysql> update aa set name='aaa' where id = 1;

#step 2:窗口二
mysql> start transaction;
mysql> update bb set name='bbb' where id = 1;

#step 3:窗口一
mysql> update bb set name='bbb';
#step 4:窗口三
#是否自动提交
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+

#查看当前连接
mysql> show processlist;
mysql> show full processlist;
mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host      | db   | Command | Time | State | Info             |
+----+------+-----------+------+---------+------+-------+------------------+
|  4 | root | localhost | test | Sleep   |  244 |       | NULL             |
|  5 | root | localhost | test | Sleep   |  111 |       | NULL             |
|  6 | root | localhost | NULL | Query   |    0 | init  | show processlist |
+----+------+-----------+------+---------+------+-------+------------------+


#查看当前正在被锁的事务(锁请求超时后则查不到)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+
| lock_id          | lock_trx_id | lock_mode | lock_type | lock_table  | lock_index      | lock_space | lock_page | lock_rec | lock_data      |
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+
| 130718495:65:3:4 | 130718495   | X         | RECORD    | `test`.`bb` | GEN_CLUST_INDEX |         65 |         3 |        4 | 0x000000000300 |
| 130718496:65:3:4 | 130718496   | X         | RECORD    | `test`.`bb` | GEN_CLUST_INDEX |         65 |         3 |        4 | 0x000000000300 |
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+

#查看当前等待锁的事务(锁请求超时后则查不到)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 130718499         | 130718499:65:3:4  | 130718500       | 130718500:65:3:4 |
+-------------------+-------------------+-----------------+------------------+


#查看当前未提交的事务(如果死锁等待超时,事务可能还没有关闭)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
+--------------------------------------------------------------------------------------------------------+
| trx_id    | trx_state | trx_started         | trx_requested_lock_id | trx_wait_started    | trx_weight |
+-----------+-----------+---------------------+-----------------------+---------------------+------------+
| 130718500 | RUNNING   | 2018-03-12 09:28:10 | NULL                  | NULL                |          3 |
| 130718499 | LOCK WAIT | 2018-03-12 09:27:59 | 130718499:65:3:4      | 2018-03-12 09:32:48 |          5 |
==========================================================================================================
| trx_mysql_thread_id | trx_query                             | trx_operation_state | trx_tables_in_use |
+---------------------+---------------------------------------+---------------------+-------------------+
|                   4 | NULL                                  | NULL                |                 0 |
|                   5 | update bb set name='bbb'              | starting index read |                 1 |
=========================================================================================================
| trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified |
+-------------------+------------------+-----------------------+-----------------+-------------------+
|                 0 |                2 |                   360 |               3 |                 1 |
|                 1 |                4 |                  1184 |               4 |                 1 |
===========================================================================================================================
| trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error |
+-------------------------+---------------------+-------------------+------------------------+----------------------------+
|                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |
|                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |
===========================================================================================================================
| trx_adaptive_hash_latched | trx_adaptive_hash_timeout | trx_is_read_only | trx_autocommit_non_locking |
+---------------------------+---------------------------+------------------+----------------------------+
|                         0 |                     10000 |                0 |                          0 |
|                         0 |                     10000 |                0 |                          0 |
+---------------------------+---------------------------+------------------+----------------------------+


#查看正在被访问的表
mysql> show OPEN TABLES where In_use > 0;
+----------+-------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | bb    |      1 |           0 |
+----------+-------+--------+-------------+
#step 3:窗口一 (若第三步中锁请求太久,则出现锁超时而终止执行)
mysql> update bb set name='bbb';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


#"窗口一" 锁请求超时前,执行第五步,使死锁产生,则该连接 "窗口二" 执行终止,"窗口一" 顺利执行
#step 5:窗口二
mysql> update aa set name='aa';
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
查看最近一个死锁情况
#查看最近一个死锁情况
mysql> SHOW ENGINE INNODB STATUS\G ;
...............
------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-03-12 11:01:06 7ffb4993a700 #发生时间
*** (1) TRANSACTION: #事务1
TRANSACTION 130718515, ACTIVE 19 sec starting index read
mysql tables in use 1, locked 1 #正被访问的表
LOCK WAIT 4 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 1 #影响行数
MySQL thread id 5, OS thread handle 0x7ffb498f8700, query id 205 localhost root updating #线程/连接host/用户
update bb set name='bb' #请求语句
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: #等待以下资源 (锁定位置及锁模式)
RECORD LOCKS space id 65 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`bb` trx id 130718515 lock_mode X waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000300; asc       ;;
 1: len 6; hex 000007ca9b34; asc      4;;
 2: len 7; hex 1f000002092075; asc       u;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6262; asc bb;;

*** (2) TRANSACTION: #事务2
TRANSACTION 130718516, ACTIVE 14 sec starting index read
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 1
MySQL thread id 4, OS thread handle 0x7ffb4993a700, query id 206 localhost root updating
update aa set name='aa' #请求语句
*** (2) HOLDS THE LOCK(S): #持有锁资源
RECORD LOCKS space id 65 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`bb` trx id 130718516 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000301; asc       ;;
 1: len 6; hex 000007ca9b17; asc       ;;
 2: len 7; hex 9000000144011e; asc     D  ;;
 3: len 4; hex 80000002; asc     ;;
 4: len 2; hex 6262; asc bb;;

Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000300; asc       ;;
 1: len 6; hex 000007ca9b34; asc      4;;
 2: len 7; hex 1f000002092075; asc       u;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6262; asc bb;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 64 page no 3 n bits 80 index `GEN_CLUST_INDEX` of table `test`.`aa` trx id 130718516 lock_mode X waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000007ca9b33; asc      3;;
 2: len 7; hex 1e000001d53057; asc      0W;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6161; asc aa;;

*** WE ROLL BACK TRANSACTION (2)
...............
#死锁记录只记录最近一个死锁信息,若要将每个死锁信息都保存到错误日志,启用以下参数:
mysql> show variables like 'innodb_print_all_deadlocks';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_print_all_deadlocks | OFF   |
+----------------------------+-------+

 
#上面 【step 3:窗口一】若一直请求不到资源,默认50秒则出现锁等待超时。
mysql> show variables like 'innodb_lock_wait_timeout'; 
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


#设置全局变量 锁等待超时为60秒(新的连接生效)
#mysql> set session innodb_lock_wait_timeout=50; 
mysql> set global innodb_lock_wait_timeout=60; 


#上面测试中,当事务中的某个语句超时只回滚该语句,事务的完整性属于被破坏了。为了回滚这个事务,启用以下参数:
mysql> show variables like 'innodb_rollback_on_timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | OFF   |
+----------------------------+-------+
最终参数设置如下:(重启服务重新连接测试)
[mysqld]
log-error =/var/log/mysqld3306.log
innodb_lock_wait_timeout=60     #锁请求超时时间(秒)
innodb_rollback_on_timeout = 1  #事务中某个语句锁请求超时将回滚真个事务
innodb_print_all_deadlocks = 1  #死锁都保存到错误日志
#若手动删除堵塞会话,删除 Command='Sleep' 、无State、无Info、trx_weight 权重最小的。
show processlist;
SELECT trx_mysql_thread_id,trx_state,trx_started,trx_weight FROM INFORMATION_SCHEMA.INNODB_TRX;


  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL中的锁表处理是指在数据库操作中,为了确保数据的一致性和并发控制,会对表进行锁定,防止其他事务对这些表进行修改或插入。这是数据库管理系统(DBMS)用来解决并发访问问题的一种机制。 1. 表级锁定(Table Locking):当对整个表进行锁定时,表上的所有行都会被锁定,无论是读还是写操作。这可能会导致性能问题,特别是在高并发场景下,因为只有一个事务能执行写操作。 2. 行级锁定(Row-Level Locking):MySQL使用InnoDB存储引擎支持行级锁定,这意味着事务只锁定它所操作的特定行,提高了并发能力。常见的行级锁定类型有共享锁(S锁)和排他锁(X锁)。 - 共享锁(S锁):多个事务可以同时对同一行进行读操作,但不允许修改。 - 排他锁(X锁):锁定行后,事务可以读取和修改该行,其他事务只能对该行加共享锁,如果试图加X锁则会阻塞。 3. 乐观锁定:这是一种无锁的并发控制策略,通过在数据中添加版本信息,假设大多数情况下并发操作不会冲突,只有在更新时检查版本号不一致才回滚。 4. 锁定粒度:MySQL还支持更细粒度的锁定,如页锁定(Locking at Page Level)和表空间锁定(Tablespace Locking),用于不同场景下的优化。 5. 锁等待和死锁:当一个事务请求一个已经被其他事务锁定的资源时,它会进入等待状态。如果多个事务相互等待对方释放资源,就可能导致死锁,这时系统通常会采取回滚策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值