mysql -死锁示例,死锁分析,解决办法

Leonardyp

共 36003字,需浏览 73分钟

 ·

2023-08-17 11:48

mysql 服务器配置

      mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.24    |
+-----------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE '%innodb_lock_wait_timeout%'//锁等待超时时间,单位秒
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
|
 innodb_lock_wait_timeout | 7200  |
+--------------------------+-------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE '%innodb_deadlock_detect%'//死锁检测
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
|
 innodb_deadlock_detect | ON    |
+------------------------+-------+
1 row in set (0.00 sec)

死锁一定很着急,先说快速解决办法

      SELECT concat('KILL ',id,';'
FROM information_schema.processlist p 
INNER JOIN  information_schema.INNODB_TRX x 
ON p.id=x.trx_mysql_thread_id 
WHERE db='demo';

>  执行 KILL 命令将线程杀死

示例:

1. 表结构

      CREATE TABLE order (
    id varchar(26) PRIMARY KEY,
    flag tinyint(4),
    order_no varchar(32),
    UNIQUE idx_order_no (order_no)
)

2. 造成死锁代码

      err := db.Transaction(func(tx *gorm.DB) error {
    //事务1 trx_id:579856
    err := tx.Exec("update order set flag=1 where order_no=?""1").Error
    if err != nil {
        fmt.Println(err)
    }
    func() {
        order :=Order{}
        if err :=db.Where("order_no = ?""1").Take(&order).Error; err != nil {
            fmt.Println(err)
        }
        order.UpdatedAt = time.Now()

        //事务2, trx_id:579857
        if err := db.Updates(&order).Error; err != nil {
            fmt.Println(err)
        }
    }()
    return nil
})

死锁分析

1. 通过 processlist 和  INNODB_TRX 查看锁定的线程 执行的 sql

      mysql> select trx_id,trx_state,trx_started,trx_requested_lock_id,INFO   FROM information_schema.processlist p  INNER JOIN  information_schema.INNODB_TRX x  ON p.id=x.trx_mysql_thread_id  WHERE db='demo' order by trx_id asc limit 3;
+--------+-----------+---------------------+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| trx_id | trx_state | trx_started         | trx_requested_lock_id                      | INFO                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
+--------+-----------+---------------------+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 579856 | RUNNING   | 2021-09-15 13:58:41 | NULL                                       | NULL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| 579857 | LOCK WAIT | 2021-09-15 13:58:41 | 140676703063368:3606:25:66:140677199640096 | UPDATE `order` SET `order_no`='1',`updated_at`='2021-09-17 19:58:41.814' WHERE `id` = 'mj7k36ec7prntetzmi5t67iqme'      |
579858 | LOCK WAIT | 2021-09-15 13:59:00 | 140676703065048:3606:25:66:140677199647888 | UPDATE `order` SET flag = 2 WHERE flag IN(1,6AND updated_at <= NOW()

2. 查看锁等待

      mysql> SELECT REQUESTING_THREAD_ID,REQUESTING_ENGINE_TRANSACTION_ID, BLOCKING_THREAD_ID,BLOCKING_ENGINE_TRANSACTION_ID FROM `performance_schema`.data_lock_waits;
+----------------------+----------------------------------+--------------------+--------------------------------+
| REQUESTING_THREAD_ID | REQUESTING_ENGINE_TRANSACTION_ID | BLOCKING_THREAD_ID | BLOCKING_ENGINE_TRANSACTION_ID |
+----------------------+----------------------------------+--------------------+--------------------------------+
|
                 9213 |                           579865 |               9201 |                         579864 |
|                 9213 |                           579865 |               9191 |                         579863 |
|
                 9213 |                           579865 |               9184 |                         579862 |
|                 9213 |                           579865 |               9170 |                         579861 |
|
                 9213 |                           579865 |               9161 |                         579860 |
|                 9213 |                           579865 |               9150 |                         579859 |
|
                 9213 |                           579865 |               9139 |                         579858 |
|                 9201 |                           579864 |               9191 |                         579863 |
|
                 9201 |                           579864 |               9184 |                         579862 |
|                 9201 |                           579864 |               9170 |                         579861 |
|
                 9201 |                           579864 |               9161 |                         579860 |
|                 9201 |                           579864 |               9150 |                         579859 |
|
                 9201 |                           579864 |               9139 |                         579858 |
|                 9191 |                           579863 |               9184 |                         579862 |
|
                 9191 |                           579863 |               9170 |                         579861 |
|                 9191 |                           579863 |               9161 |                         579860 |
|
                 9191 |                           579863 |               9150 |                         579859 |
|                 9191 |                           579863 |               9139 |                         579858 |
|
                 9184 |                           579862 |               9170 |                         579861 |
|                 9184 |                           579862 |               9161 |                         579860 |
|
                 9184 |                           579862 |               9150 |                         579859 |
|                 9184 |                           579862 |               9139 |                         579858 |
|
                 9170 |                           579861 |               9161 |                         579860 |
|                 9170 |                           579861 |               9150 |                         579859 |
|
                 9170 |                           579861 |               9139 |                         579858 |
|                 9161 |                           579860 |               9150 |                         579859 |
|
                 9161 |                           579860 |               9139 |                         579858 |
|                 9150 |                           579859 |               9139 |                         579858 |
|
                 9139 |                           579858 |               9138 |                         579857 |
|                 9139 |                           579858 |               9141 |                         579856 |
|
                 9138 |                           579857 |               9141 |                         579856 |
+----------------------+----------------------------------+--------------------+--------------------------------+
31 rows in set (0.00 sec)

从上面看出 579857t2) 事务等待 579856t1
579858t3) 等待 579856t1


3. 查看具体加锁情况

mj7k36ec7prntetzmi5t67iqme 是 id
bk5jhtgd5fy9pnyzw51zoocgir 是 id

      mysql> select engine_transaction_id,thread_id,object_name,index_name,lock_type,lock_mode,lock_status,lock_data from `performance_schema`.data_locks order by  engine_transaction_id asc limit 6;
+-----------------------+-----------+-------------+--------------+-----------+---------------+-------------+--------------------------------------------------+
| engine_transaction_id | thread_id | object_name | index_name   | lock_type | lock_mode     | lock_status | lock_data                                        |
+-----------------------+-----------+-------------+--------------+-----------+---------------+-------------+--------------------------------------------------+
|
                579856 |      9141 | order       | PRIMARY      | RECORD    | X,REC_NOT_GAP | GRANTED     | 'mj7k36ec7prntetzmi5t67iqme'                     |
|                579856 |      9141 | order       | idx_order_no | RECORD    | X,REC_NOT_GAP | GRANTED     | '1''mj7k36ec7prntetzmi5t67iqme' |
|
                579856 |      9141 | order       | NULL         | TABLE     | IX            | GRANTED     | NULL                                             |
|                579857 |      9138 | order       | PRIMARY      | RECORD    | X,REC_NOT_GAP | WAITING     | 'mj7k36ec7prntetzmi5t67iqme'                     |
|
                579857 |      9138 | order       | NULL         | TABLE     | IX            | GRANTED     | NULL                                             |
|                579858 |      9139 | order       | PRIMARY      | RECORD    | X             | GRANTED     | 'bk5jhtgd5fy9pnyzw51zoocgir'                     |
+-----------------------+-----------+-------------+--------------+-----------+---------------+-------------+--------------------------------------------------+
6 rows in set (0.00 sec)

579856 对记录mj7k36ec7prntetzmi5t67iqme加行级排他锁,579857 WAITING 等待 579856 锁释放,

代码: :579856 事务需要等待 579857 事务提交,结果记录 mj7k36ec7prntetzmi5t67iqme 死锁,

579858 更新多条 order 记录,多条符合条件的记录加 X 锁 ,其中包含记录 mj7k36ec7prntetzmi5t67iqme 由于需要等待 579856,造成锁等待。

总结

事务嵌套事务,579856579857 更新同一条记录,造成事务互相等待,谁也无法提交。
另,579858 范围更新订单 sql 包含 579856 同一条订单,导致锁的范围进一步扩大。

是否兼容 IS(意向共享锁) IX(意向排他锁) S X
IS 否(是,则指的表级排他锁)
IX 否(是,则指的表级排他锁)
S
X

tips

加读锁

select * FROM order WHERE id='id' LOCK IN SHARE MODE
//必须在事务中,事务提交锁自动释放

mysql 简单查询默认不加锁,通过 MVVC 快照读,实现非锁定读 X 不生效,加读锁 X 才生效

IX 不影响表的 INSERT 和 非锁定行的 DELETE

浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报