专栏首页MySQL技术事务的本质和死锁的原理

事务的本质和死锁的原理

仅以MySQL和Spring为例,本文不介绍事务和锁的概念。

本文使用伪代码表示方法代码,仅仅表达方法的意义及事务注解。

事务的形状

在我心中,事务一直是这个样子的

x轴是上锁的资源,y轴是消耗的时间,

事务方块随着时间的流逝向下移动,

当碰触x轴时资源加锁,越过x轴时资源解锁

上图是对于方法a的事务形状,我起名【 事务方块】。

@Transactional
function a(){
    对A表修改,耗时五秒
}

一、多事务

当一个方法调用多个被事务注解的子方法时情况是

上图是对于方法abc调用时,a方法、b方法、c方法的事务形状

function abc(){
    this.a(){}
    this.c(){}
}
@Transactional
function a(){
    对A表修改,耗时五秒
}
@Transactional
function b(){
    对B表修改,耗时五秒
}
@Transactional
function c(){
    对C表修改,耗时五秒
}

其中abc方法开始执行时,执行到a方法,锁定a表,当a方法结束b方法开始时,a表解锁,b表锁定,当b方法结束c方法开始时,b表解锁c表锁定。

相当于下图的三个事务方块联合且相对位置锁定一起下落,总运行时间15秒

如果并发请求两次abc方法则事务方块如下图

其中a表会先被请求1锁定5秒后解锁,再被请求2锁定5秒,

其中b表也会先被请求1锁定5秒后解锁,再被请求2锁定5秒,

其中c表也会先被请求1锁定5秒后解锁,再被请求2锁定5秒,

而请求1在解锁表a后紧接着又锁定了表b五秒,同时表a再被请求2锁定5秒

依次类推,请求2都在请求1解锁对应的表之后,锁定该表,

那么总运行时间20秒。

二、大事务

@Transactional
function abc(){
    this.a(){}
    this.b(){}
    this.c(){}
}
function a(){
    对A表修改,耗时五秒
}
function b(){
    对B表修改,耗时五秒
}
function c(){
    对C表修改,耗时五秒
}

其中abc方法上有事务注解,而子方法a、b、c上没有事务注解,事务方块形状如下图

a、b、c三个颜色的方块是结合在一起的只能一起执行,那么a表被锁定15秒,b表被锁定10秒,c表被锁定5秒

如果也并发请求两次abc方法则总耗时30秒,显而易见事务方块越大,耗时越长。

在这个abc方法中,事务锁定表是懒锁定的方式,就是说

当abc中a方法开始执行时,只锁定了a表,执行完a方法后,

开始执行b方法锁定b表,此时a表不解锁,当b方法执行完后,

开始执行c方法锁定c表,此时a、b两个表都不解锁,当c方法执行完后,a、b、c三个表一起解锁。

这就造成了以下情况。

三、死锁

有如下两个方法ab和ba

@Transactional
function ab(){
    this.a(){}
    this.b(){}
}
@Transactional
function ba(){
    this.b(){}
    this.a(){}
}

当ab和ba方法同时被执行时,事务方块类似下图,但不完全

当ab和ba方法同时被执行时,ab锁定a表,ba锁定b表,

当ab执行完a方法请求锁定b表时,ba也执行完了b方法请求锁定a表,

但ab没有解开对a表的锁定,ba也没有解开对b表的锁定,那么相互等待对方解锁,这就是死锁。

所以减少死锁出现的几率的办法是减小事务方块的大小,即减小事务方块消耗的时间或减小事务方块锁定的资源【表或行】

所以行级锁不易出现死锁,表级锁易出现死锁,是因为行级锁事务方块小,但消耗时间不一定,还是需要参考事务消耗时间。

如果主键是int类型自增id,则相当于把事务可锁定资源从一个表分成了21亿份的行,可见使用行级锁时事务方块明显变小。

四、名称来历

事务方块的名字来历是因为联想到俄罗斯方块,俄罗斯方块是为了给方块找一个位置放置,而事务方块是为了给方块找一个时间间隙执行通过,两者目的不同。

很抱歉我不会做动图,请自行联想俄罗斯方块下落的情况。

也可以类比成要过桥的车辆,桥宽度固定,有的车占用一车道,有的车占用两车道,有的车占用半车道,

车的形状多种多样,如老式武装三轮摩托车像ab方法的小车,大客车就是一车道的长车,自行车是半车道的小车。类似的情形很多,可自行联想。

本文分享自微信公众号 - MySQL技术(mysqljishu)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MySQL事务简介

    在学习 MySQL 的过程中,事务永远是一项绕不开的话题,日常程序开发也经常会用到事务。本篇文章将以 MySQL 8.0 版本为基础,一起来深入了解下 MySQ...

    MySQL技术
  • 【MySQL】Xtrabackup备份工具使用

    备份前准备: 修改InnoDB为独立表空间模式,即在my.cnf中[mysqld]下设置innodb_file_per_table=1 建议创建一个单独的备份目...

    MySQL技术
  • 是时候学习Linux了

    Linux是一个开源、免费的操作系统。其稳定性、安全性、处理多并发已经得到业界的认可,目前很多企业级的项目都会部署到Linux/unix系统上。如果你还不太了解...

    MySQL技术
  • 带你白嫖程序带宽限制命令Trickle

    前天一个研发的兄弟问我,实现完成了ClickHouse数据备份的功能,然后把数据上传到HDFS之类的文件系统中,但是提交给测试,发现程序把网卡带宽跑满了,就向我...

    后场技术
  • GitHub的R包毕竟没那么可靠,你要学会自己解决报错

    最近又需要使用一个肿瘤外显子看cnv的R包,根据全局的vcf文件,就是FACETS,发表该包的文章是:FACETS: allele-specific copy ...

    生信技能树
  • thinkPHP+LayUI 流加载实现功能

    以上所述是小编给大家介绍的thinkPHP+LayUI 流加载实现功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大...

    砸漏
  • 地震信号的一些基本概念

    可控震源是指通过一个与大地紧密耦合的振动平板,以反作用方式向地下传送一组连续振动的弹性波信号(又称扫描信号),再经过对地面接收到的反射波信号的处理和辨识,用于解...

    DSPSTACK.COM
  • 专访 | CVPR PAMI青年研究员奖得主Andreas Geiger:自动驾驶中的计算机视觉

    在今年 6 月召开的 CVPR2018 上,德国图宾根大学及马克斯·普朗克研究所(MPI)自动视觉组负责人 Andreas Geiger 教授摘得了 PAMI ...

    机器之心
  • TiDB 在摩拜单车的深度实践及应用

    摩拜单车 2017 年开始将 TiDB 尝试应用到实际业务当中,根据业务的不断发展,TiDB 版本快速迭代,我们将 TiDB 在摩拜单车的使用场景逐渐分为了三个...

    PingCAP
  • 笔记:NEC QTP 第二个实例

    Set testWindow=new ClassJavaWindow testWindow.SetJavaWindow("User Login") Set i...

    超级大猪

扫码关注云+社区

领取腾讯云代金券