百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

MySQL专题2: 事务和锁

ccwgpt 2024-11-25 10:24 60 浏览 0 评论

说说数据库事务特性及存在的问题

这属于数据库事务的基础概念了, 就是ACID

  • Atomicity, 原子性, 事务包含的所有操作要么全部成功, 要么全部失败回滚.
  • Consistency, 一致性, 事务执行前后, 数据库的数据要保持一致性.
  • Isolation, 隔离性, 事务的执行不受其它事务的影响, 并发执行的几个事务互不影响. 事务执行的中间结果对其它事务必须是透明的. 关于隔离性, 数据库提供了多种隔离级别.
  • Durability, 持久性, 是指一个事务一旦被提交了, 那么对数据库中的数据的改变就是永久的, 不会丢失的.

ACID是一种理想状态, 数据库是通过一些机制来保证ACID的, 但是在实际使用中, 为了兼顾功能容量和性能会对其中的某一项或多项作出折衷.



谈谈对Innodb事务的理解

事务具有ACID四个特性: 原子性, 一致性, 隔离性, 持久性

InnoDB对ACD这三个特性是通过 Redo log 和 Undo log 实现的, 对I(隔离性)是通过锁来实现的.

Redo Log

用来实现事务的持久性, 即D特性. 它由两部分组成:

  1. 内存中的重做日志缓冲
  2. 重做日志文件

InnoDB 在事务提交时, 必须先将该事务的所有日志写入到 Redo Log 中, 待事务的 Commit 操作完成才算整个事务操作完成

Undo Log

Undo Log 可以实现如下两个功能:

  1. 实现事务回滚
  2. 实现MVCC (Multiversion concurrency control, 多版本并行控制)

Undo Log 和 Redo Log 记录物理日志不一样, 它是逻辑日志: 当删除一条记录时, Undo Log 中会记录一条对应的 Insert 记录, 反之亦然; 当 Update 一条记录时, 它记录一条对应反向的 Update 记录. 当执行回滚时, 就可以从 Undo Log 中的逻辑记录读取到相应的内容并进行回滚.



什么是MySQL隔离级别?

InnoDB默认是可重复读的 REPEATABLE READ. MySQL/InnoDB 提供SQL标准所描述的所有四个事务隔离级别, 可以在命令行用--transaction-isolation选项, 或在选项文件里为所有连接设置默认隔离级别. 例如可以在my.inf文件的[mysqld]节里类似如下设置该选项:

transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}

隔离级别         脏读(Dirty Read) 不可重复读(NonRepeatable Read)     幻读(Phantom Read)
未提交读(Read uncommitted)  可能         可能                可能
已提交读(Read committed)    不可能       可能                 可能
可重复读(Repeatable read)   不可能       不可能               可能
可串行化(Serializable )     不可能       不可能               不可能
  • 未提交读(Read Uncommitted): 允许脏读, 也就是可能读取到其他会话中未提交事务修改的数据
  • 提交读(Read Committed): 只能读取到已经提交的数据. Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read): 可重复读. 在同一个事务内的查询都是事务开始时刻一致的, InnoDB默认级别. 在SQL标准中, 该隔离级别消除了不可重复读, 但是还存在幻象读
  • 串行读(Serializable): 完全串行化的读, 每次读都需要获得表级共享锁, 读写相互都会阻塞

不同的读:

  • 脏读: 脏读就是指当一个事务正在访问数据, 并且对数据进行了修改, 而这种修改还没有提交到数据库中, 这时, 另外一个事务也访问这个数据, 然后使用了这个数据.
  • 不可重复读: 是指在一个事务内多次读同一数据, 而在这个事务还没有结束时另外一个事务也访问并修改同一数据. 那么在第一个事务中的两次读数据之间, 由于第二个事务的修改, 读到的的数据不一样了. 这样就发生了在一个事务内两次读到的数据不一致, 称为不可重复读.
  • 幻读: 第一个事务先开始, 其修改涉及到某个表的全部数据行, 在未提交时第二个事务向这个表插入一行新数据. 此时会发生操作第一个事务的用户发现表中存在没有修改的数据行, 这称为幻读.



有多少种事务失效的场景, 如何解决?

  • 如使用MyISAM, 则事务会不起作用
  • 如果使用了 SpringMVC, 则 context:component-scan 重复扫描问题可能会引起事务失败.
  • @Transactional 注解开启配置, 必须放到 Listener 里加载, 如果放到 DispatcherServlet 的配置里, 事务也是不起作用的
  • @Transactional 注解只能应用到 public 可见度的方法上. 如果你在 protected, private 或者 package-visible 的方法上使用 @Transactional 注解, 它不会报错, 但是事务也无效
  • 在具体的类(或类的方法)上使用 @Transactional 注解, 而不要使用在任何接口上. 在接口上使用 @Transactional 注解, 只在你设置了基于接口的代理时它才生效



一致性非锁定读和一致性锁定读是什么?

一致性非锁定读 consistent nonlocking read 是InnoDB存储引擎通过多版本控制 multi versioning 的方式来读取当前执行时间数据库中的数据.

如果被读的数据行被加了排他锁, 在读取这行数据的时候并不会等待锁释放, 而是读取该行的一个快照数据. 之所以称为非锁定读, 因为不需要等待被访问行的X锁的释放. 快照数据是指修改行之前的数据版本, 该实现通过undo段来完成. 非锁定读的方式极大提高了数据库的并发性. 在InnoDB存储引擎中, 这是默认的读取方式.

在默认情况下, InnoDB存储引擎对数据采用的是一致性非锁定读. 但是有些情况下为了保证数据逻辑的一致性, 需要对SELECT的操作加锁. InnoDB 存储引擎对于 SELECT 语句支持两种一致性的锁定读(locking read)操作

  1. SELECT …… FOR UPDATE
  2. SELECT …… LOCK IN SHARE MODE



Innodb如何解决幻读?

幻读问题是指一个事务的两次不同时间的相同查询返回了不同的的结果集. 例如: 一个 select 语句执行了两次, 但是在第二次返回了第一次没有返回的行, 那么这些行就是 Phantom Row.

Read view(或者说 MVCC)实现了一致性非锁定读(Consistent Nonlocking Reads), 从而避免了幻读.

一致性读是通过 MVCC 为查询提供了一个基于时间的点的快照, 这个查询只能看到在自己之前提交的数据, 而在查询开始之后提交的数据是不可以看到的. 一个特例是,这个查询可以看到于自己开始之后的同一个事务产生的变化.



谈谈MySQL的锁并发?

谈谈Innodb行锁?

相对于串行处理来说, 并发事务处理能大大增加数据库资源的利用率, 提高数据库系统的事务吞吐量, 从而可以支持更多的用户. 但并发事务处理也会带来一些问题, 主要包括以下几种情况

  • 更新丢失(Lost Update): 当两个或多个事务选择同一行, 然后基于最初选定的值更新该行时, 由于每个事务都不知道其他事务的存在, 就会发生丢失更新问题 -- 最后的更新覆盖了由其他事务所做的更新. 例如, 两个编辑人员制作了同一文档的电子副本. 每个编辑人员独立地更改其副本, 然后保存更改后的副本, 这样就覆盖了原始文档. 最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改. 如果在一个编辑人员完成并提交事务之前, 另一个编辑人员不能访问同一文件, 则可避免此问题.
  • 脏读(Dirty Reads): 一个事务正在对一条记录做修改, 在这个事务完成并提交前, 这条记录的数据就处于不一致状态;这时, 另一个事务也来读取同一条记录, 如果不加控制, 第二个事务读取了这些“脏”数据, 并据此做进一步的处理, 就会产生未提交的数据依赖关系. 这种现象被形象地叫做"脏读".
  • 不可重复读(Non-Repeatable Reads): 一个事务在读取某些数据后的某个时间, 再次读取以前读过的数据, 却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”.
  • 幻读(Phantom Reads): 一个事务按相同的查询条件重新读取以前检索过的数据, 却发现其他事务插入了满足其查询条件的新数据, 这种现象就称为“幻读”.

InnoDB实现了以下两种类型的行锁.

  • 共享锁(S): 允许一个事务去读一行, 阻止其他事务获得相同数据集的排他锁.
  • 排他锁(X): 允许获得排他锁的事务更新数据, 阻止其他事务取得相同数据集的共享读锁和排他写锁.

另外, 为了允许行锁和表锁共存, 实现多粒度锁机制, InnoDB还有两种内部使用的意向锁(Intention Locks), 这两种意向锁都是表锁.

  • 意向共享锁(IS): 事务打算给数据行加行共享锁, 事务在给一个数据行加共享锁前必须先取得该表的IS锁.
  • 意向排他锁(IX): 事务打算给数据行加行排他锁, 事务在给一个数据行加排他锁前必须先取得该表的IX锁.



死锁及监控是什么?

死锁是由于两个或两个以上会话锁等待产生回路造成

死锁监控及处理方法: 对于死锁的监控, 各个版本都提供了innodb_print_all_deadlocks选项, 打开该选项即会将死锁的日志输出到MySQL的错误日志当中, 因此可以通过监控错误日志来达到监控死锁的目的

如何降低死锁发生的概率

  1. 尽量使用短小事务, 避免大事务
  2. 加FOR UPDATE/LOCK IN SHARE MODE锁时, 最好降低事务隔离级别, 例如用RC(Read Committed, 已提交读)级别, 降低死锁发生概率, 也可以降低锁定粒度. 默认是Repeatable Read, 可重复读.
  3. 事务中涉及多个表, 或者涉及多行记录时, 每个事务的操作顺序都要保持一致
  4. 通过索引优化SQL效率, 降低死锁概率, 避免全表扫描导致锁定所有数据
  5. 程序中应有事务失败检测及自动重复提交机制
  6. 高并发(例如秒杀)场景中, 关闭innodb_deadlock_detect选项, 降低死锁检测开销, 提高并发效率



自增长与锁 , 锁的算法, 锁问题, 锁升级是什么?

首先, mysql的记录插入有三种情况:

  • Simple inserts, 简单插入, 执行前就能确定插入的记录个数
  • Bulk inserts, 批量插入, 像inset select这种, 在插入前不确定记录个数
  • Mixed inserts, 一次插入多条数据, 但是其中部分数据指定了自增ID的值的情况.

5.1.22之前InnoDB自增值是通过其本身的自增长计数器来获取值, 该实现方式是通过表锁机制来完成的AUTO-INC LOCKING, 锁不是在每次事务完成后释放, 而是在完成对自增长值插入的SQL语句后释放, 要等待其释放才能进行后续操作. 比如说当表里有一个auto_increment字段的时候, innoDB会在内存里保存一个计数器用来记录auto_increment的值, 当插入一个新行数据时, 就会用一个表锁来锁住这个计数器, 直到插入结束. 如果大量的并发插入, 表锁会引起SQL堵塞.

5.1.22之后InnoDB为了解决自增主键锁表的问题, 引入了参数innodb_autoinc_lock_mode, 该实现方式是通过轻量级互斥量的增长机制完成的, 专门用来在使用auto_increment的情况下调整锁策略. innodb_autoinc_lock_mode可以设定3个值: 0, 1, 2, 默认使用的是1

  • 0: traditonal传统的, 通过表锁的方式进行, 所有类型的insert都用 auto-inc locking
  • 1: consecutive连续的, 默认值, 这种模式下insert语句在开始时会获得一个表锁autoinc_lock, simple insert在获取到需要增加的ID的量后autoinc_lock就会被释放, 不必等到语句执行结束. 但对于bulk insert, 自增锁会被一直持有直到语句执行结束才会被释放.
  • 2: interleaved插入式的隔行扫描的, 这种模式下没有auto_inc 锁了, 不会锁表, 并发性能最高. 这时候产生的自增ID, 是跨语句分布的, 并发执行的插入语句所产生的记录的ID可能并不连续. 如果是simple inserts, 那么单个语句内ID还是连续的, 但是像bulk insert单个语句内就未必是连续了. 这种模式可能会导致Statement 的 Replication 出现不一致, 使用该模式, 需要用 Row Replication的模式



乐观锁的线程如何做失败补偿?

失败后自动重试, 设定好次数限制



高并发场景如何防止死锁, 保证数据一致性?

数据库使用version做乐观锁避免更新被覆盖和超卖
使用队列串行化请求, 避免峰值
使用计数器切换活动状态, 达到一定量后立即关闭活动, 降低服务器负载


来源:https://www.cnblogs.com/milton/p/15857307.html

“做程序员,圈子和学习最重要”因为有有了圈子可以让你少走弯路,扩宽人脉,扩展思路,学习他人的一些经验及学习方法!同时在这分享一下是一直以来整理的Java后端进阶笔记文档和学习资料免费分享给大家!需要资料的朋友私信我扣【06】

相关推荐

团队管理“布阵术”:3招让你的团队战斗力爆表!

为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...

知情人士回应字节大模型团队架构调整

【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...

豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍

强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...

创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)

创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...

消息称吴永辉入职后引发字节大模型团队架构大调整

2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...

31页组织效能提升模型,经营管理团队搭建框架与权责定位

分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...

异形柱结构(异形柱结构技术规程)

下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...

职场干货:金字塔原理(金字塔原理实战篇)

金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...

底部剪力法(底部剪力法的基本原理)

某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...

结构等效重力荷载代表值(等效重力荷载系数)

某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...

体系结构已成昭告后世善莫大焉(体系构架是什么意思)

实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...

框架柱抗震构造要求(框架柱抗震设计)

某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...

梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)

某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...

死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?

活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...

不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么

最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...

取消回复欢迎 发表评论: