什么是事务
事务是指是程序中一系列严密的逻辑操作,而且所有操作必须全部成功完成,否则在每个操作中所作的所有更改都会被撤消。可以通俗理解为:就是把多件事情当做一件事情来处理,好比大家同在一条船上,要活一起活,要完一起完 。
事务四大特性
原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。这是可靠数据库所应具备的几个特性。
原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某一个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度,串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交,读提交,可重复读,串行化。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
ACID是靠什么保证的?
1、原子性是由undolog日志来保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功是sql。
2、一致性是由其他三大特征保证,程序代码要保证业务上的一致性。
3、隔离性是由MVCC来保证
4、持久性由redolog来保证,MySQL修改数据的时候会在redolog中记录一份日志数据,就算数据没有保存成功,只要日志保存成功了,数据仍然不会丢失。
脏读、不可重复度、幻读
- Dirty Read:脏读:一个事务读取到了中间结果(最终不一定提交,有可能rollback的结果)
- Fuzzy Read:不可重复读: 一个事务中前后两次读取同一个记录,读取的结果不相同。主要针对update操作,一个事务在更新过程中,其它事务更新并提交成功。
- Phantom:幻读:主要针对insert操作操作。一个事务在更新记录,另一个事务插入新的记录,看上去前一个事务没有生效。
事务的隔离级别
SQL 标准定义了四种隔离级别, MySQL 全都⽀持. 这四种隔离级别分别是:
-
读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.
因为其他事务未提交的数据可能会发⽣回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.
-
读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据,
该隔离级别不会有脏读的问题.但由于在事务的执⾏中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读
-
可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同⼀事务多次查询的结果⼀致, 但是其他事务新插⼊的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别。
⽐如此级别的事务正在执⾏时, 另⼀个事务成功的插⼊了某条数据, 但因为它每次查询的结果都是⼀样的, 所以会导致查询不到这条数据, ⾃⼰重复插⼊时⼜失败(因为唯⼀约束的原因). 明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去, 这个现象叫幻读
-
串⾏化(SERIALIZABLE): 序列化, 事务最⾼隔离级别. 它会强制事务排序, 使之不会发⽣冲突, 从⽽解决了脏读, 不可重复读和幻读问题, 但因为执⾏效率低, 所以真正使⽤的场景并不多.
什么是MVCC
MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照。
什么是间隙锁
间隙锁(Gap Locks)是数据库中用于锁定索引范围的一种锁。它们的主要目的是防止其他事务在给定范围内插入新的数据,保证范围内数据的一致性和避免幻读现象。
当你执行一个范围查询并使用
SELECT … FOR UPDATE
或者在事务中执行某些操作时,数据库会为查询结果的范围使用间隙锁。这个范围包括了满足查询条件的现有数据行之间的间隙。
举个例子,假设你执行了一个范围查询
SELECT * FROM table WHERE id BETWEEN 10 AND 20 FOR UPDATE;
这个查询会获取范围在 10 到 20 之间的数据行,并且对这个范围的间隙(即 9 到 21 之间的索引空间)也会加上间隙锁,防止其他事务在这个范围内插入新的数据行。
间隙锁的作用是防止幻读(Phantom Read)的发生。幻读指的是在一个事务中,两次相同的查询返回了不同数量的行,这可能是因为其他事务在此期间插入了新的数据。通过间隙锁,数据库确保在范围查询期间,其他事务无法在查询范围内插入新的数据行,从而保证了查询结果的一致性。
需要注意的是,间隙锁可能会对并发性能产生一些影响,因为它会锁定索引范围而不是具体的数据行。因此,在设计数据库时需要权衡使用间隙锁对并发性能的影响以及数据的一致性需求。
参考:什么是间隙锁