ACID特性
原子性(Atomicity)
单个事务,为一个不可分割的最小工作单元,整个事务中的所有操作要么全部commit成功,要么全部失败rollback,对于一个事务来说,不可能只执行其中的一部分SQL操作,这就是事务的原子性。
一致性(Consistency)
数据库总是从一个一致性的状态转换到另外一个一致性的状态。
隔离性(Isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。
持久性(Durability)
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。
ACID具体实现
对MySQL来说,逻辑备份日志(binlog)、重做日志(redolog)、回滚日志(undolog)、锁技术 + MVCC就是MySQL实现事务的基础。
原子性:通过undolog来实现。
持久性:通过binlog、redolog来实现。
隔离性:通过(读写锁+MVCC)来实现。
一致性:MySQL通过原子性,持久性,隔离性最终实现数据一致性。
隔离性
隔离级别
隔离性是事务ACID特性里最复杂的一个。在SQL标准里定义了四种隔离级别,每一种级别都规定一个事务中的修改,哪些是事务之间可见的,哪些是不可见的。
级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大。
隔离级别 | 效果 |
---|---|
读未提交(RU) | 一个事务还没提交时,它做的变更就能被别的事务看到。(别的事务指同一时间进行的增删改查操作) |
读提交(RC) | 一个事务提交(commit)之后,它做的变更才会被其他事务看到。 |
可重复读(RR) | 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。 |
串行(xíng)化(S) | 正如物理书上写的,串行是单线路,顾名思义在MySQL中同一时刻只允许单个事务执行,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。 |
MVVC
MVCC(Mutil Version Concurrency Control)多版本并发控制,是一种并发控制的方法(而非具体实现),一般在数据库管理系统中,实现对数据库的并发访问。
MVVC外链
1.版本链
2.ReadView
在RC隔离级别下,每一次快照读都会生成一个最新的ReadView;
在RR隔离级别下,只有事务中第一次快照读会生成ReadView,之后的快照读都使用第一次生成的ReadView。
事务隔离级别为RC(读已提交隔):
2、事务隔离级别为RR(可重复读):
通过readView可以更容易区分开
隔离级别 | 效果 |
---|---|
读提交(RC) | 一个事务提交(commit)之后,它做的变更才会被其他事务看到。 |
可重复读(RR) | 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。 |
bin log
binlog 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。
binlog 是 mysql的逻辑日志,逻辑日志:可以简单理解为记录的就是sql语句 。
binlog使用场景
在实际应用中, binlog 的主要使用场景有两个,分别是 主从复制 和 数据恢复 。
redo log
redo log 包括两部分:一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件( redo logfile)。
先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。
循环写
为啥缺一不可
1.在上图时刻A中,也就是写入redo log处于prepare阶段以后、写binlog之前,发生了崩溃(crash):由于此时binlog还没写,redo log也还没提交(commit),所以崩溃恢复的时候,这个事务会回滚。这时候,binlog还没写,所以也不会传到备库,数据一致;
2.在上图时刻B中,也就是写完binlog之后,发生crash:如果redo log里面的事务有commit标识(事务是完整的)则直接提交;如果redo log里面的事务只有prepare没有commit,则判断对应的事务在binlog是否存在并完整,完整则提交事务,否则回滚事务;
3.MySQL怎么知道binlog是完整的:一个事务的binlog是有完整格式的,statement格式(记录sql语句),最后会有个COMMIT; row格式(记录行的内容,记两条,更新前和更新后都有),最后会有个XID event
4.redo log和binlog是怎么关联起来的:他们有一个共同的数据字段XID。崩溃恢复的时候,会按顺序扫描redo log;上述第二点中的崩溃恢复场景(redo log里面的事务只有完整的prepare而没有commit),那么mysql就会拿着XID去binlog找是否存在对应的完整事务;