MySQL学习-01-InnoDB与ACID

InnoDB与ACID[2]

A 原子性

MySQL针对原子性的设计主要涉及InnoDB的事务功能,通过COMMIT与ROLLBACK将原本多个原子性操作变成一个原子性操作,COMMIT将事务提交后事务内的所有操作统一生效,若出现错误则ROLLBACK撤销未提交的所有操作,这样通过事务的提交和撤销可以使事务中的所有操作生效与失效都保持统一,保证所有操作的原子性


C 一致性

一致性指事务必须使数据库的状态转变必须是从一个正确的状态到另一个正确的状态,这里的正确指数据库的状态始终保证在指定的约束下,比如一个int数据约束为大于0,则无论数据库进行怎样的状态转变,该数据都必须始终大于0

在MySQL中,一致性有相当一部分通过InnoDB的双写缓存区和崩溃恢复实现

双写缓存区 是一个存储区域,包括内存(128页 = 2MB)与磁盘(128页 = 2个区 = 2MB),分别以DoubleWrite Buffer和DoubleWrite File形式存在

在InnoDB将页面写入InnoDB数据文件中的适当位置之前,首先将数据写入DoubleWrite Buffer中(由于内存的读写很快,所以数据完整性强),再通过后台线程将内存中的数据存入DoubleWrite File中(存入磁盘保证数据持久性),然后确认写入后将数据写入InnoDB数据文件,在这个过程中如果发生崩溃,则崩溃恢复时可以通过双写缓存区中的数据和redo log恢复数据;同时在写入数据文件前已经将应有的所有数据都保存在内存中,所以不会出现数据只写入一半的情况,保证了数据库的一致性


I 隔离性

隔离性指多个用户并发访问数据库时,数据库为每一个用户开启的事务不能被其他事务的操作所干扰

四个隔离级别(读未提交 读已提交 可重复读 串行化)

1.读未提交是最低的隔离级别,即每个用户都能看到其他用户的未提交事务的执行结果,会出现脏读/不可重复读/幻读问题

2.读已提交,即每个用户都只能看到其他用户的已经提交的事务的执行结果,可以避免脏读(读取到最终没有修改的数据(修改但未提交)),会出现不可重复读/幻读

3.可重复读,执行事务时会锁定查询的行和列,避免其他事务修改,即同一事务的多个实例在并发读取数据时,会看到相同的数据行,可以避免脏读和不可重复读(一个事务执行时可能会多次读取同一数据,而同时另一事务在多次读取的间隙修改了该数据,从而导致多次读取的数据不同),会出现幻读

4.串行化是最高的隔离级别,即强制事务串行执行,在读取的每一行数据都加上锁,可以避免幻读(与不可重复读相似,在一个事务多次读取数据的间隙,另一个事务增加/减少了数据,导致多次读取的数据数量不同)(不可重复读需要锁行,而幻读需要锁表)

值得一提的是,由于读未提交的隔离级别在事务发生时几乎没有使用锁来保证隔离性,所以性能是最高的,拥有非常高的并发处理能力和很低的系统开销;相对的,串行化作为最高的隔离级别在事务发生时非常频繁地使用锁,会导致大量的超时现象和锁竞争,性能不好,只有非常需要数据隔离性的业务才会使用

一般的数据库大多默认使用 读已提交 这一隔离级别,而MySQL默认使用 可重复读 这一隔离级别


D 持久性[3]

持久性指一个事务一经提交则永久性地改变数据库,即使发生系统故障已提交的事务也不会丢失

双写缓存区在这里依然扮演重要的角色,此处我们更多地分析redo log

redo log是InnoDB特有的只记录修改存储引擎产生的日志文件,使用了WAL(Write Ahead Logging)提前写日志的技术,即发生了数据修改的操作时先把该操作写入日志中,等空闲时再把该修改持久化到磁盘里

redo log包含两部分:redo log bufffer与redo log file,为了减少不必要的io操作,事务在执行的过程中产生的redo log首先会写入buffer中,之后统一存入file刷盘进行持久化,这个动作被称之为fsync(文件同步);在InnoDB后台存在一个后台线程mater thread,每隔一秒就会把buffer中的日志文件写到文件系统缓存page cache,然后调用fsync持久化磁盘

引用

[1]https://mysql.net.cn/doc/refman/8.0/en/mysql-acid.html
[2]https://blog.csdn.net/footpath/article/details/123333259
[3]https://blog.csdn.net/qq_25448409/article/details/105376450

你可能感兴趣的:(MySQL学习-01-InnoDB与ACID)