MySQL 死锁模拟及分析

38 阅读1分钟

一、死锁模拟

1)创建表base_account_item 并且插入两条数据

CREATE TABLE base_account_item (
                                   id INT(11) NOT NULL,
                                   account_item_name VARCHAR(50) NOT NULL,
                                   PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO base_account_item (id, account_item_name) VALUES (1, '本金1');
INSERT INTO base_account_item (id, account_item_name) VALUES (2, '本金2');

2)开启一个客户端 执行事务A

# 事务A
START TRANSACTION;
SELECT * FROM base_account_item WHERE id = 1 FOR UPDATE;
-- 不提交或回滚,保持连接开启
SELECT SLEEP(5);
SELECT * FROM base_account_item WHERE id = 2 FOR UPDATE;

3)开启另外一个客户端执行事务B

# 事务B
START TRANSACTION;
SELECT * FROM base_account_item WHERE id = 2 FOR UPDATE;
-- 等待连接
SELECT SLEEP(5);
SELECT * FROM base_account_item WHERE id = 1 FOR UPDATE;

4)产生死锁

image.png

二、总结

1)mysql死亡是否会自动释放及死锁的定义

MySQL会自动检测事务死锁并立即回滚其中一个事务,并返回一个错误。 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进程称为死锁进程。

2)如何避免死锁

  1. 优化SQL语句,减少锁定时间,避免相互等待锁的代码
  2. 调整事务隔离级别。
  3. 减少事务的长度。
  4. 尽量避免在事务中进行大量的更新操作。