Mysql四大特性:
1、原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
2、一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态, 换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
3、隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
4、持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障, 也不应该丢失。
背后实现
概念
1. redo
redo, 重做日志,保证了事务的原子性与持久性。通常是物理日志,用于恢复事务修改的页操作。
redo 包括两部分:
1 内存中的重做日志缓冲,易失,一般在事务开始时,就要写入这部分
2 第二部分是重做日志,这个是要刷如磁盘的。一般在事务提交时会刷如磁盘。有些场景,也可以设置没用每次事务提交就刷,而是交给master thread 定期刷盘,但是这样如果在这期间,宕机了,则没有刷盘的数据就要丢失了。
redo 日志里面存储的是操作指令,每个指令根据操作类型的不同,存储格式也是不同的。
redo 在内存中,结合了checkpoint 以及LSN(log sequence number) 来保证刷入磁盘的数据不丢。checkpoint记录了刷磁盘刷到哪儿了,LSN记录了当前内存中的日志编号。二者之间的内容就是没有刷新到磁盘的日志。
2. undo
undo保证了事务的一致性。undo 并不是物理日志,而是逻辑上的日志,有一个专门的内存字段存储undo 日志。
undo 主要有两个作用:1是回滚操作,将数据库逻辑地恢复到原来的样子,但是已经分配的页、或者数据结果可能回滚不了了; 2 是MVCC(多版本并发控制),实现并发控制的一种很通用的机制,在下面的一节中,我们会讲到。
当事务提交的时候,innodb不会立即删除undo log,因为后续还可能会用到undo log,如隔离级别为repeatable read时,事务读取的都是开启事务时的最新提交行版本,只要该事务不结束,该行版本就不能删除,即undo log不能删除。
但是在事务提交的时候,会将该事务对应的undo log放入到删除列表中,未来通过purge来删除。并且提交事务时,还会判断undo log分配的页是否可以重用,如果可以重用,则会分配给后面来的事务,避免为每个独立的事务分配独立的undo log页而浪费存储空间和性能。
至于purge后台进程的删除操作https://blog.csdn.net/zwleagle/article/details/44567251
我就不再赘述(毕竟我不也懂)
3. binlog
binlog基本定义:二进制日志,也成为二进制日志,记录对数据发生或潜在发生更改的SQL语句,并以二进制的形式保存在磁盘中
作用:Mysql的作用类似于ORACLE的归档日志,可以用来查看数据库的变更历史(具体的时间点所有的SQL操作)、数据库增量备份和恢复(增量备份和基于时间点的恢复)、Mysql的复制(主主数据库的复制、主从数据库的复制)
ARIES(WAL)原则
先写日之后写磁盘,日志成功写入后就不会丢失,后续由checkpoint机制来保证磁盘物理文件与redo日志达到一致性。
利用Redo 记录变更后的数据,即redo记录事务数据变更后的值
利用Undo 记录变更前的数据,用于回滚和其他事务多版本读。
有了如上概念的基础就可以更好的理解四个特性的背后实现
原子性的实现
每一个写事务,都会修改 Buffer Pool,从而产生相应的 Redo 日志,这些日志信息会被记录到 ib_logfiles 文件中。因为 Redo 日志是遵循 Write Ahead Log 的方式写的,所以事务是顺序被记录的。
任何 Buffer Pool 中的页被刷到磁盘之前,都会先写入到日志文件中。
回滚(undo日志)
要保证原子性,就必须在异常发生时,对已经执行的操作进行回滚,此时就用到了undo 日志。
未刷盘数据提交(redo日志)
除了回滚之外,还有一种场景是事务提交了,日志写入到buffer pool 了,但是buffer pool的脏页 并没有刷盘,那此时怎么恢复呢?就需要用到redo日志恢复数据。
综合上述两种case,其实原子性的保证就是用到了WAL的原则。
持久性的实现
持久性是表示一个事务一旦提交,它对数据的改变就是永久的。通过原子性可以保证的一旦事务提交,即使遇到宕机,也可以从逻辑上将数据找回来,再次写入到物理存储空间。
当事务提交的时候会把所有的修改信息存放在redo log中,并且会把redo log持久化到磁盘,当电脑重启后就会重新执行redo log的修改信息来恢复数据,这样就能够达到持久化的目的。
因为redo日志是有限的,那么宕机之后,redo日志之前的数据怎么恢复呢,会结合binlog日志。
隔离性的实现
innodb隔离性有四种,我们简单看一下四种隔离级别都是怎么实现的。
1、读未提交:没做任何控制。能够读到一个事务中的中间状态,是违背ACID的,所以在MySQL中基本不用。
2、读已提交(RC):通过对数据加了写锁,在写的过程中数据是不能被其他事务看到的。但是会存在不可重复读的问题。
3、可重复读(RR):通过增加间隙锁,解决了不可重读的问题,但是并不能对未存在的数据进行加锁操作,所以会存在幻读的问题。(innodb默认)
4、可串行化:通过加锁,所有的操作都是单版本,串行化的。
一致性的实现
一致性可以归纳为完整性。而数据的完整性是通过上面三个特性来保证的,包括原子性、隔离性、持久性,而这三个特性又是通过Redo/Undo/binlog 来保证的