序言:ACID 是一组数据库设计原则,他是业务数据和关键业务程序的可靠性保障。
1、atomicity(原子性)
依赖如下能力
autocommit
commit
rollback
2、一致性
2.1 double write buffer
1、定义:double write buffer 是一块空间,mysql 将缓冲池的数据写入到此空间,然后 flush 到 mysql 数据存储空间。当 mysql 发生异常退出时,会从这个空间恢复数据。
2、可能问题:double write buffer 会造成两倍磁盘IO 吗?
不会,写入double write buffer 使用OS 调用 fsync()方法,每次写入一块大的 chunk 数据。(顺序 IO)
2.2 crash recovery
mysql 异常恢复分为如下几步进行
2.2.1 tablespace discovery
mysql 启动时会扫描tablespace空间,看是否有表需要 recovery。
2.2.1 redo log application
重要知识:checkpoint(检查点) 是 redo log 管理的核心机制之一。它的核心作用是 标记哪些数据修改已经持久化到磁盘,从而优化崩溃恢复的效率并回收 redo log 空间
1、redo log 存储方式:redo log,存储物理日志 记录数据页的变化(即第几页第几行变动),用于 mysql 程序异常退出后恢复。
redo log 在磁盘中是一系列文件,在事务成功提交并且写入后会被清理,此空间会重复使用
2、redo log 的写入:写入 redo log buffer,默认事务提交时强制刷盘 innodb_flush_log_at_trx_commit。(可每秒刷盘 0 ,OS 异步刷盘)
2.2.2 回滚未提交事务
2.2.3 change buffer merge
redo log 中会存储buffer pool 和 change buffer 中的数据,在 redo log 重放时,会根据 checkpoint 位置恢复对应的 change buffer
2.2.4 purge
清除被标记删除的,并且在所有事务中不可见的数据。
3、隔离性
3.1 隔离级别
1、REPEATABLE READ:事务开启时read snapshot,snapshot 在事务执行中不会变化,除非本事务使用 DML语句。 在执行 DQL,DML 语句时会使用 gap lock。这也是REPEATABLE READ减少幻读的核心。
2、READ COMMITTED:每次 read 都是读取最新的 snapshot,在 select,update delete 时根据 where 条件匹配到 row,然后使用 primary key 或者隐藏主键锁住 row,而不会使用 gap lock 锁住间隙。READ COMMITTED确保最终一致性,且会有更好的并发性能。
3、READ UNCOMMITTED:产生脏读,幻读,一般不用。
4、SERIALIZABLE:禁用并发。
3.2 data lock
4、持久性
mysql数据持久性主要和 redo log,double write buffer,bin log 相关联,除此之外,还与 mysq 服务所在的机器相关,如 CPU,OS,hardware。下面从 mysql 自身支持持久性分析:
1、如图可知 Redo Log 和 double write buffer的数据都来自 buffer pool 中的脏页,这两类数据都是以磁盘存储,buffer pool 是内存存储。
2、Redo log 和 double write buffer 都是 mysql 的恢复机制,当 mysql recovery 时首先从 double write buffer 恢复,如果恢复失败或者部分恢复,则会从 redo log 恢复。
3、innodb_flush_log_at_trx 参数的配置会影响 mysql 数据持久性,默认配置 1,Redo log 同步刷盘才返回客户端成功,其他两种情况均可能导致 mysql 丢失数据。
4、mysql server 层还有 bin log,它存储 mysql 事务提交后的每一条逻辑数据(SQL),常用做主从复制和数据同步。
下图是 mysql 写入数据时的流程图