首先,什么是ACID?
原子性(A):
原子性就是一个事务内的操作,要么全部成功,要么全部失败。
一致性(C)
一致性就是一个正确的结果到另一个正确的结果。换句话说就是一个事务造成的结果要符合我们的常理,
比如一个账户5000元钱,那么我最多就只能取出5000块,不能取6000甚至10000块出来。
隔离性(I)
隔离性就是两个事物之间不会相互影响
持久性(D)
持久性就是将数据从内存写到磁盘中存储。一旦一个事务提交了,那么对于数据的改变是永久性的,不会因为
服务器崩溃或者数据库崩溃等情况导致数据被篡改或消失。
如何保证原子性
简单来说,数据库通过undolog日志来保证原子性。它记录了需要回滚的日志信息。事务发生回滚时,
会读取日志,撤销已经执行成功的sql语句
如何保证一致性
一致性是通过其他三大特性来保证的。
如何保证隔离性
通过MVCC来保证事务的隔离性。
如何保证持久性
通过redolog日志来保证。在我们进行增删改数据的时候,会先在redolog日志中保存。然后再将数据写入到磁盘。
因为修改数据是在磁盘中随机读写,而写入日志文件是顺序读写,顺序读写的效率要明显高于随机读写。因此,
只要数据保存到了redolog中,即使之后读写磁盘的过程发生了故障,也不会造成数据的丢失。
例如:服务器意外宕机,innoDB可以根据redolog日志重新恢复到宕机前的状态,以此保证数据的完整性。
引申问题,如何保持redolog与binlog的一致?
参考 https://zhuanlan.zhihu.com/p/470489184
为了解决两份日志之间的逻辑一致问题,InnoDB存储引擎使用两阶段提交方案。原理很简单,将redo log的写入拆成了两个步骤prepare和commit,这就是两阶段提交。使用两阶段提交后,写入binlog时发生异常也不会有影响,因为MySQL根据redo log日志恢复数据时,发现redo log还处于prepare阶段,并且没有对应binlog日志,就会回滚该事务。
那么如果redo log在commit阶段发生异常是否会回滚呢?
并不会回滚事务,它会执行上图框住的逻辑,虽然redo log是处于prepare阶段,但是能通过事务id找到对应的binlog日志,所以MySQL认为是完整的,就会提交事务恢复数据。