加入收藏 | 设为首页 | 会员中心 | 我要投稿 汽车网 (https://www.0577qiche.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL 数据库的死锁

发布时间:2023-09-06 13:07:44 所属栏目:MySql教程 来源:
导读:死锁是指两个或多个事务在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。当多个事务尝试以不同的顺序锁定资源,或者多个事务同时锁定同一个资源,都有可能产生死锁。
死锁是指两个或多个事务在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。当多个事务尝试以不同的顺序锁定资源,或者多个事务同时锁定同一个资源,都有可能产生死锁。

场景:两个事务同时处理 customer 表

两个事务同时执行了第一条 update 语句,更新并锁定了该行数据,紧接着又都执行第二条 update 语句,此时发现该行已经被对方锁定,然后两个事务都等待对方释放锁,同时又持有对方需要的锁,陷入死循环,需要外力介入才能解除死锁。

MysqL> CREATE TABLE `customer` (
  `id` int() NOT NULL,
  `last_name` varchar() DEFAULT NULL,
  `first_name` varchar() DEFAULT NULL,
  `birth_date` date DEFAULT NULL,
  `gender` char() DEFAULT NULL,
  `balance` decimal(,) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

事务:
start transaction;
update customer set balance =  where id = ;
update customer set balance =  where id = ;
commit;

事务:
start transaction;
update customer set balance =  where id = ;
update customer set balance =  where id = ;
commit;

为了解决死锁问题,数据库实现了各种死锁检测和死锁超时机制。越复杂的存储引擎,越能检测到死锁的循环以来,并返回错误,这是一种比较有效的办法。还有一种解决死锁的办法是:当锁等待超时后,放弃锁请求。

InnoDB 存储引擎可以自动检测事务的死锁,并回滚一个或几个事务来防止死锁。但是有些场景 InnoDB是无法检测到死锁的,比如在同一事务中使用 InnoDB 之外的存储引擎、lock tables 设定表锁定的语句,此时要通过设置 innodb_lock_wait_timeout 这个系统参数来解决。通过锁等待超时来解决死锁问题,通常不是好的办法,因为很有可能导致大量事务的锁等待。当发生锁等待超时,数据库会抛出如下报错信息:
ERROR  (HY000): Lock wait timeout exceeded; try restarting transaction  

调整 innodb_lock_wait_timeout 的方法有两种:

临时:在MysqL中直接用命令行执行
-- innodb_lock_wait_timeout的默认值为50秒
MysqL> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout |     |
+--------------------------+-------+
 row in set ( sec)
MysqL> set innodb_lock_wait_timeout=;
Query OK,  rows affected ( sec)

永久:将以下两个参数添加至配置文件 my.cnf,并重启 MysqL:
innodb_lock_wait_timeout=

我们在程序设计时,也要尽可能的减小死锁发生的概率。以下是针对 InnoDB 存储引擎减小死锁发生概率的一些建议:
类似业务模块,尽可能按照相同的访问顺序来访问,防止产生死锁;
同一个事务中,尽可能做到一次锁定需要的所有资源,减少死锁发生概率;
同一个事务中,不要使用不同存储引擎的表,比如 MyISAM 和 InnoDB 表出现在同一事务中;
尽可能控制事务的大小,减少锁定的资源量和锁定时间长度;
对于容易产生死锁的业务模块,尝试升级锁颗粒度,通过表级锁减少死锁发生概率。

(编辑:汽车网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章