.Mysql是如何保证事务的?
事务的ACID特性,原子性、一致性、隔离性、一致性。
msyql是有缓存的,修改先到缓存,随后刷新到磁盘,如果没有刷新到磁盘,系统崩溃了,怎么办?
我们要求事务要么全部执行,要么全部不执行,事务其实已经执行完了,只是数据在内存中,那么怎么恢复呢?
这就需要我们有恢复机制,MySQL设计了RedoLog,顾名思义,重做日志,失效以后重试。如果让你设计重做日志,你会怎么做?找个日志文件,不停地往里面写,系统崩溃了,就从某个点恢复。现在问题来了,某个点是哪个点?如何知道。是不是需要维护一个记录恢复点的数据。还有一个问题,那些刷新到磁盘的数据,他们对应的redo日志是不是没有意义了,我们就没有必要保存了,所以我们的日志文件不需要无限大,是可以删除之前的数据的,MySQL中则采用覆盖。这个时候是不是又需要有个标记,哪个位置的数据可以覆盖。
所以redo log成了一个环,这个环有几个日志文件组成,从第0个文件开始,一直到最后一个,如果写满了,从第0个文件开始覆盖。每个redo日志都有一个序号,叫作LSN,上文提到的恢复点叫 check point lsn, check point之前的日志文件都是已经同步到磁盘的日志,是可以删除的,也就是可以覆盖了。
写日志也是有缓存的,日志也是先在缓存(崩溃了,这些日志怎么办?崩溃了丢失1s的数据)中,然后写入磁盘。
RedoLog与Binlog
有了redo log,为啥还需要binlog呢?
1、redo log的大小是固定的,日志上的记录修改落盘后,日志会被覆盖掉,无法用于数据回滚/数据恢复等操作。
2、redo log是innodb引擎层实现的,并不是所有引擎都有。
来自:https://www.jianshu.com/p/4bcfffb27ed5
redoLog是Innodb搜索引擎特有的,而binlog是MySQL服务端,只要有sql执行就需要记录binlog。
那么问题来了,binlog和redolog先写哪个?
假设一个事务执行完了,先写入binlog,然后宕机了,redolog没有写,这个时候master机器的数据是不影响的,但是binlog已经同步到从机器了,这就导致了主从不一致。
假设,先写redolog, 然后宕机了,binlog没写,这个时候master机器事务重做,完成了。 从机器的没有收到binlog,结果,还是主从不一致。
这个时候就需要采用新的方式,两阶段提交。
图片来自:https://www.jianshu.com/p/4bcfffb27ed5
这样就可以保证redolog和binlog同时成功或失败,解决了数据不一致的问题,但是有可能丢死更新。