死锁-MySQL

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 死锁 MySQL

1、死锁

在操作系统中,死锁是指两个或两个以上的进程,每个进程都无限等待被改组进程中另一个进程所占有的资源,因而永远无法得到资源,这种现象称为进程死锁。

那么在数据库中,我们将操作系统对死锁的定义进行简单替换,将进程替换为事务即可。

数据库死锁是指两个或两个以上的事务,每个事务都在无限等待被改组事务中另一个事务所占有的资源,因而无法得到资源。

2、死锁必要条件

只要发生了死锁,这四个条件一定存在。

  1. 互斥使用(独占资源)

在数据库中,互斥使用的资源大部分都是表和行。

  1. 占有且等待

一个事务先锁定了行A,然后又申请锁定行B;另一个事务先申请锁定了行B,然后有申请锁定行A;当这两个事务以一种时序执行时就会产生死锁。

  1. 不可抢占

事务与事务之间是隔离的,肯定不可以一个事务抢占另一个事务的资源,必须要等待事务资源释放资源。

  1. 循环等待

当事务和资源形成一条有向有环图时。使用资源分配图来表示一下(蓝色先表示有回路):

1.png

3、SQL示例


-- 创建用户余额表
CREATE TABLE `user_balance` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `balance` int NOT NULL COMMENT '余额',
  PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '用户余额';

-- 插入2条记录
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);


-- 事务A
BEGIN;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=1;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=2;
COMMIT;


-- 事务B
BEGIN;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=2;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=1;
COMMIT;

如果恰好事务A和事务B都执行了第一行UPDATE,接着事务A和事务B都去执行第二条UPDATE语句,此时发现id=1和id=2的数据都被锁定且不是自己,那么事务A和B都在相互等待锁释放,则陷入了死锁状态。

4、解决方案

为了解决死锁问题,数据库实现了各种死锁检测和死锁超时机制。InnoDB存储引擎可以检测到死锁的循环依赖并立即返回操作。

InnoDB目前处理死锁的方式是将持有最少行排他锁的事务进行回滚。

5、死锁复现

按照使用上面的SQL在MySQL 8.0版本执行SQL进行死锁复现,截图如下:

  1. 事务A正常执行

2.png

  1. 事务B被回滚

3.png

6、总结

  1. MySQL 的死锁并不可怕,死锁后只需要在业务代码进行重试即可(官方建议)

7、参考

  1. 高性能MySQL(第三版)
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
关系型数据库 MySQL 中间件
【MySQL实战笔记】07 | 行锁功过:怎么减少行锁对性能的影响?-02 死锁和死锁检测
【4月更文挑战第19天】在高并发环境下,死锁发生在多个线程间循环等待资源时,导致无限期等待。MySQL中,死锁可通过`innodb_lock_wait_timeout`参数设置超时或`innodb_deadlock_detect`开启死锁检测来解决。默认的50s超时可能不适用于在线服务,而频繁检测会消耗大量CPU。应对热点行更新引发的性能问题,可以暂时关闭死锁检测(风险是产生大量超时),控制并发度,或通过分散记录减少锁冲突,例如将数据分拆到多行以降低死锁概率。
19 1
|
2月前
|
SQL 关系型数据库 MySQL
MySQL - 死锁的产生及解决方案
MySQL - 死锁的产生及解决方案
199 0
|
3月前
|
算法 关系型数据库 MySQL
MySQL相关(九)- 死锁的发生和避免
MySQL相关(九)- 死锁的发生和避免
25 0
|
3月前
|
SQL 关系型数据库 MySQL
MySQL事务原理分析(ACID特性、隔离级别、锁、MVCC、并发读异常、并发死锁以及如何避免死锁)
MySQL事务原理分析(ACID特性、隔离级别、锁、MVCC、并发读异常、并发死锁以及如何避免死锁)
89 1
|
4月前
|
关系型数据库 MySQL 调度
KnowStreaming系列教程第四篇——MySQL数据更新死锁问题
KnowStreaming系列教程第四篇——MySQL数据更新死锁问题
43 0
|
4月前
|
SQL 存储 关系型数据库
MySQL 意向共享锁、意向排他锁、死锁
MySQL 意向共享锁、意向排他锁、死锁
51 0
MySQL 意向共享锁、意向排他锁、死锁
|
5月前
|
SQL NoSQL 关系型数据库
Mysql Innodb死锁情况分析与归纳
Mysql Innodb死锁情况分析与归纳
54 0
|
6月前
|
存储 SQL 关系型数据库
MySQL 优化 index merge(索引合并)引起的死锁分析(强烈推荐)
生产环境出现死锁流水,通过查看死锁日志,看到造成死锁的是两条一样的update语句(只有where条件中的值不同),如下:
|
6月前
|
SQL 关系型数据库 MySQL
Mysql死亡笔记的死锁记录
Mysql死亡笔记的死锁记录
69 0
|
6月前
|
关系型数据库 MySQL 中间件
MySQL学习笔记-死锁和死锁检测
MySQL学习笔记-死锁和死锁检测
51 0