mysql 事务及隔离级别,锁

本文深入探讨了数据库事务的ACID特性,包括原子性、一致性、隔离性和持久性,并详细解析了四种事务隔离级别:未提交读、提交读、可重复读和串行化,以及如何避免脏读、不可重复读和幻读等问题。

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

1. 事务特性:ACID

  1. 原子性: 回滚日志(undo log)
  2. 持久性: 重做日志(redo log)
  3. 隔离性: 锁+mvcc(当前读)
  4. 一致性:(通过AID及用户自定义完整性保证)
    一致性是事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要应用层面进行保障(转账)。

一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。不同于CAP的一致性,CAP的一致性指的是多个节点数据保持一致,

2. 事务隔离级别

在这里插入图片描述

未提交读(问题:脏读)-> 提交读(问题:不可重复读)-> 可重复读(默认)(问题:幻读 )-> 串行化或者mvcc(读)及X锁+gap锁(写)

幻读
指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row). —高性能mysql(权威)

不可重复度
一个事务内两次读之间,另一个事务修改了数据,两次读的内容不一样

可重复读
一个事务启动的时候,能够看到所有已经提交的事务结果。但是之后,这个事务执行期间,其他事务的更新对它不可见

mysql如何实现避免幻读

  • 在快照读读情况下,mysql通过mvcc来避免幻读
  • 在当前读读情况下,mysql通过next-key来避免幻读

mvcc

InnoDB 的MVCC ,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number) 。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。下面看一下在REPEATABLE READ 隔离级别下, MVCC 具体是如何操作的。

SELECT
InnoDB 会根据以下两个条件检查每行记录:
a. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号)这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
b.行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除。
只有符合上述两个条件的记录,才能返回作为查询结果。
INSERT
InnoDB 为新插入的每一行保存当前系统版本号作为行版本号。
DELETE
InnoDB 为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE
InnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统 版本号到原来的行作为行删除标识。

什么是next-key锁

可以简单的理解为记录锁(X锁(排他锁))+GAP锁

什么是快照读和当前读

  • 快照读:一致性读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。
    简单的select操作,属于快照读,不加锁

select * from table where ?;

  • 当前读:当前读就是读取最新数据,而不是历史版本的数据
    特殊的读操作,插入/更新/删除操作,DML 操作,属于当前读,需要加锁。

select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;

行锁

在这里插入图片描述

间隙锁

间隙锁之间都不存在冲突关系,间隙锁的引入,可能会导致同样的语句锁住更大的范围,这其实是影响了并发度的 。可重复读隔离级别下才会生效的

3. 锁

锁类别

表级锁(alter table,LOCK TABLES users READ),myisam仅支持表锁
行级锁(Record Lock)
间隙锁(Gap Lock)
Next-key Lock:(Record Lock + Gap Lock)
共享锁
排它锁:普通select不会加锁,所以某个事务在一行加排它锁,其他事务的普通select能执行,只是查询的是老数据
意向共享/排它锁

意向锁:

作用:一个任务想要获取表级别的应用共享或排它锁,则受到由第一个任务控制的表级别意向锁的阻塞。第二个任务在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁。

innoDB 支持多粒度的锁,允许表锁和行锁的并存,为了方便多粒度锁冲突的判断,innoDB 中还存在一种名叫意向锁(Intention Locks)的锁

取得行的共享锁和排他锁之前需要先取得表的意向共享锁(IS)和意向排他锁(IX),主要是用来辅助表级和行级锁的冲突判断,因为 Innodb 支持行级锁,如果没有意向锁,则判断表锁和行锁冲突的时候需要遍历表上所有行锁,有了意向锁,则只要判断表是否存在意向锁就可以知道是否有行锁了

意向锁,表级别的锁
意向锁不会与行级的共享 / 排他锁互斥!!!
在这里插入图片描述

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值