mysql事务常见问题

本文探讨事务的原子性、隔离性、持久性和一致性,解析脏读、不可重复读、幻读问题,以及在InnoDB中如何避免死锁,特别关注可重复读隔离级别下的幻读解决方案和加锁策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务的目的:事务将数据库从一种一致性状态转换为另一种一致性状态;

组成:可以由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成

特征:在数据库提交事务时,可以确保要么所有修改都已经保存,要么所有修改都不保存;事务时访问并更新数据库各种数据项的一个程序执行单元;在MySQL innodb下,每一条语句都是事务;可以通过set autocommit = 0;设置当前会话手动提交。

ACID特性:

原子性(A)

  • 事务操作要么都提交要么都回滚;通过undolog记录事务每步具体操作,回滚时就回放事务具体操作的逆运算

隔离性(I)

  • 每个读写事务的对象与其他事务的操作对象能互相分离,并发事务之间不会互相影响;有不同成都的隔离级别,通过MVCC和锁来实现,三种粒度加锁,表(聚集索引B+树)、页(聚集索引B+树叶子节点)、行(叶子节点当中某一段记录行)

持久性(D)

  • 事务提交后,事务DML操作会持久化,写入redolog,即使宕机等故障数据库也能将数据回复,redolog记录的是物理日志

一致性(C)

  • 事务执行前后,事务完整性没有被破坏;一个事务单元需要提交之后才会对其他事务可见

并发异常:读异常 和 死锁

如果用myisam都只有表锁,不会出现这个并发异常

用innodb有行锁和并发就会出现

读异常

 重点在于隔离级别为 可重复读 的时候,如何解决幻读和提交覆盖的问题?是如何加锁的?

脏读

描述:事务A可以读到事务B中未提交的数据,出现在 读未提交 的隔离级别

解决办法:提升隔离级别为 读已提交 级别以上,因为 读已提交 的读操作有mvcc版本控制,读取最新版本的行数据。

不可重复读

描述:事务A可以读到另外一个事务B中提交的同一行数据;通常发生正一个事务中两次读到的数据是不一样的情况,一般出现在 读未提交 和 读已提交 的隔离级别,一般不会带来很大的问题,不可重复读问题是可以接受的

解决办法:提升隔离级别为 重复读 级别以上,mvcc版本控制,读取的是事务开始之前的行数据,是一个快照读,其他并行事务修改不会影响当前的事务,但是当前的事务(当前读)自己中间修改是可更新的。

幻读

描述:两次读取同一个范围内的记录得到的结果集不一样;出现在 可重复读 的隔离级别及以下;

解决办法:事务开始前加锁,持续锁,可重复读 隔离级别会在范围内加间隙锁,事务提交或者回滚的时候,释放锁。这样其他事务就没办法对这个范围的行数据进行增删改。

读锁也就是共享锁S,语句后加上 lock in share mode;

写锁也就是排他锁X,语句后加上 for update;

丢失更新1) 回滚覆盖

描述:事务A修改了一行数据在提交前,事务B回滚了这行数据导致事务A修改无效;数据库做了改动,拒绝产生这种情况

丢失更新2) 提交覆盖

描述:事务A先修改了数据未提交,事务B后修改且提交了同一行数据,此时事务A才提交覆盖了事务B的操作;

解决办法:和幻读一样加锁

区别

脏读和不可重复读:脏读是读了另一个事务未提交的数据,不可重复读是读取另一个事务修改的已提交数据,本质上都是其他事务影响了本事务的读取;

不可重复读和幻读:不可重复读是两次读取同一条记录,得到不一样的结果;幻读是两次读取同一个范围内的记录得到的结果集不一样;

并发死锁

描述

死锁:两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象; MySQL 中采用 wait-for graph (等待图-采用非递归深度优先的图算法实现)的方式来进行死锁检 测; 异常报错:deadlock found when trying to get lock;

场景

相反加锁顺序:1)不同表的加锁顺序相反,或者相同表内不同行加锁顺序相反造成死锁;2)可能出现在外键索引是给父表加锁,同时隐含给子表加锁;

解决办法:调整加锁顺序

锁冲突死锁:innodb在RR(可重复读)隔离级别下,最常见的是插入意向锁与gap锁冲突造成死锁,原理是一个事务想要获取插入意向锁,如果有其他事务加了gap lock或 Next-key lock则会阻塞。

解决办法:更换语句或者降低隔离级别;

如何避免死锁

  • 尽可能以相同顺序来访问索引记录和表;
  • 如果能确定幻读和不可重复读对应用影响不大,考虑将隔离级别降低为RC;
  • 添加合理的索引,不走索引将会为每一行记录加锁,死锁概率非常大;
  • 尽量在一个事务中锁定所需要的所有资源,减小死锁概率;
  • 避免大事务,将大事务分拆成多个小事务;
  • 大事务占用资源多,耗时长,冲突概率变高;
  • 避免同一时间点运行多个对同一表进行读写的概率;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值