1. A:Atomicity,原子性
- 原子性
一个事务必须被视为一个不可分割的最小单位,要不全部提交成功,要么全部失败回滚
- 实现:undo log
undo log称之为回滚日志,每条数据的变化(insert/update/delete)都会产生一条记录,并且日志持久化到磁盘,undo log用来记录数据修改前的信息,比如说要插入一条记录,那么undo log就会记录一条删除该信息的语句,这样你需要回滚的时候那么undo log就会执行删除你之前插入的那条记录,达到没有修改前的状态,更新一个记录也会生成一条sql记录你更新前的字段状态,从而实现了原子性。
2. C:Consistency,一致性
- 一致性
数据库总是从一个一致性的状态转换到另外一个一致性状态,不会部分数据状态改变而另一部分数据状态没有改变
数据一致性是最基本的属性,其它的三个属性都为了保证一致性而存在的。
3. I:Isolation,隔离性
- 隔离性
通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的
- 实现:锁
- 参考:数据库——MySQL事务
4. D:Durability,持久性
- 持久性
一旦事务提交,则其所做的修改会被永久保存到数据库中
- 实现:redo log
mysql为了提升性能不会把每次的修改都实时同步到磁盘中,而是先存到缓存中,然后再使用线程去做缓冲池和磁盘中的同步。这样必然会存在问题,假如电脑突然停电,那么没有持久化到磁盘的信息必然会丢失,那么持久性如何实现?答:redolog
- 关于记录日志
redo log叫重做日志,记录的是数据修改之后的值,不管事务是否提交都会记录下来。在实例和介质失败(media failure)时,redo log文件就能派上用场,如数据库掉电,InnoDB存储引擎会使用redo log恢复到掉电前的时刻,以此来保证数据的完整性。在空闲的时候或者是按照设定的更新策略将redo log中的内容更新到磁盘中
- 关于持久化日志
在空闲的时候或者是按照设定的更新策略将redo log中的内容更新到磁盘中,这里涉及到WAL即Write Ahead logging技术,他的关键点是先写日志,再写磁盘。
- 结果
有了redo log日志,那么在数据库进行异常重启的时候,可以根据redo log日志进行恢复,也就达到了crash-safe。
- 结构
redo log日志的大小是固定的,即记录满了以后就从头循环写
- 扩展:binlog
1、binlog是server层实现的,意味着所有引擎都可以使用binlog日志
2、binlog通过追加的方式写入的,可通过配置参数max_binlog_size设置每个binlog文件的大小,当文件大小大于给定值后,日志会发生滚动,之后的日志记录到新的文件上。
3、binlog有两种记录模式,statement格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有。
作者:会玩code 链接:https://www.jianshu.com/p/4bcfffb27ed5 来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 扩展:两阶段提交
- 为什么需要两阶段提交:
binlog是MySQL中Server层的日志,redo log是InnoDB存储引擎特有的。
如果先写redo log然后写binlog:如果redo log写完后,写binlog的时候,MySQL进程异常重启。但是我们redo
log写入了这条更新,所以重启后这条数据依然会被修改。但是因为binlog还没有写完就崩溃了,当我们需要用binlog来恢复临时库的时候就发现少了一次更新,这时候就会发生不一致。
如果先写binlog然后写redo log:如果binlog写完之后,redo
log还没有写完就异常重启。那么InnoDB引擎就会判断事物无效,回滚这次操作。但是binlog里面却记录了这次操作。当我们使用binlog来恢复的时候就又多了一个事务,这时候又会数据不一致。
- 两阶段出现故障:
时刻A发生故障:这时候发生故障的话,redo log处于prepare阶段,此时redo
log还没有提交所以崩溃恢复的时候这个事务就会回滚本次提交。因为binlog还没有写,所以恢复数据的时候也不会执行此次事务
时刻B发生了故障:如果时刻B说明redo
log处于prepare阶段,并且binlog已经写完了。但是执行器调用存储引擎提交事务时候,redo
log还没来记得修改为commit的时候发生崩溃。那么此时就需要分情况。重启过后InnoDB引擎发现redo
log是prepare阶段,那么就会根据自己的XID去寻找对应的binlog(XID是他们共同的数据字段)。如果binlog是完整的,这时候极有可能binlog已经被备库同步了,那么此时直接提交事务。如果binlog不是完整的,那么此时回滚事务。
看到这里不知道你会不会有一个疑惑。处于prepare状态的redo log和完整的binlog就可以崩溃恢复了,为什么还要再设计redo
log的commit阶段?
我们继续用反证法,如果没有commit阶段的话。当我们写入redo
log后事务提交,然后写binlog的时候写入失败发生了崩溃。但是事务已经提交了,就不能回滚了。如果允许回滚的话,提交事务和写binlog这之间其他事务也对这条记录进行修改,回滚就会覆盖其他事务的更新。
———————————————— 版权声明:本文为CSDN博主「活在梦里丶」的原创文章,遵循CC 4.0
BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_25448409/article/details/105376450