《Mysql技术内幕,Innodb存储引擎》——事物
事物
- 事物中的操做要么都成功要么都不作,这是事物的目的,也是事物模型与文件系统的重要特征之一。
- 扁平事物(Flat Transactions) 全部操做都处于同一层次,要么都作要么都执行要么都回滚,没法提交或回滚一部分。由于其模型简单而普遍使用。
- 带保存点的扁平事物(Flat Transaction with Savepoint) 与扁平事物相比其容许在执行过程当中回滚到某一个较早的状态(savepoint),保存点 用来记住事物当前的状态。保存点在事物内部是递增的,即便回滚事后。
- 链事物(Chained Transaction) 提交一个事物时,释放不须要的对象,将必要的对象隐式地传给下一个要开始的事物。也就是说提交事物和开始下一个事物合并成了一个原子操做。其回滚仅限于当前事物。
- 嵌套事物(Nested Transaction) 层次嵌套事物,能够当作一颗事务树。叶子节点是扁平事物,子事物既能够提交也能够回滚,树中任意一个事物的回滚将引发其全部子事物的回滚,所以子事物只保留了ACI而不具备D的特性。
- 分布式事物(Distributed Transaction) 分布式环境下运行的扁平事物。
事物的实现
redo
1. 基本概念mysql
- 重作日志用于实现持久性,由redo log buffer和redo log file两部分组成。
- Innodb在commit时必须先将事物的全部redo log写入到redo log file进行持久化。
- 为了确保redo log的持久性,在每次将重作日志缓冲写入日志文件后将调用一次fsync(缘由在于写入日志文件不少时候只是写入文件系统的缓存,调用fsync则直接写入了磁盘)。
- 为了提升commit的性能,也能够设置等待一个时间周期后再执行fsync,但极可能致使数据丢失。
- redo log是属于存储引擎层的日志,记录每一个页的修改。而二进制日志则是数据库层的日志记录的是操做对应的SQL语句。
2. 日志结构sql
- redo log以512B的块(block)进行存储,称为重作日志块(redo log block)。
- 因为512B与磁盘扇区同样大,所以能够保证其写入的原子性,因此不须要double write来保证数据一致性。
- log block中包括lob block header、log block 和log block tailer三部分。
- log group(重作日志组)其中有多个重作日志文件,每一个文件大小相同。
- 重作日志文件中存储的就是log buffer中保存的log block,所以物理存储也是以block管理。
- log buffer刷到文件规则:事物提交、log buffer中有一半的内存已经被使用和log checkpoint。
- 每一个redo log file的前2KB不写入block,由于log group中第一个文件将写入一些信息。
3. LSN数据库
- Log Sequence Number,日志序列号,递增。
- LSN表示重作日志写入的字节总量,checkpoint的位置,页数据的版本(Innodb检测是否须要恢复就是根据页的LSN与redo log中LSN对比)。
- innodb重启时都会尝试着恢复数据,恢复时只须要回复checkpoint开始的日志部分。
undo
1. 基本概念缓存
- undo log是为事物回滚准备的,MVCC也依赖于undo log。
- undo存放在undo段中,undo段位于共享表空间。
- undo是逻辑日志,只是将数据库逻辑地恢复到事物前的样子,所以回滚后可能数据结构和页自己都不同了。
2. 存储管理数据结构
- Innodb中有rollback segment,每一个回滚段中记录1024个undo log segment,在undo log segment中进行undo页的申请。
- innodb 1.1以前只有一个rollback segment,1.1后支持最大128个,所以同时支持事物的限制为128*1024.
- 事物在写入undo log时一样会写入redo log(undo也是写入数据到页中)。
- 事物提交后不能立刻删除undo log,由于可能MVCC在使用,所以将其放入一个链表中,删除与否由purge线程判断。
- undo log放入链表后,若是该页的使用空间小于3/4,则表示该页还能够被重用。
- undo log的列表是以记录的进行组织的,而undo log中存放不一样事物的undo log,所以purge在回收时涉及磁盘的离散读取操做。
- insert undo log事物提交后能够直接删除。
- update undo log是对delete和update操做产生的undo log,须要支持MVCC所以不能够直接删除,须要purge线程判断。
pruge
- delete和update操做通常不直接删除原数据而是在汇集索引上标记该记录的delete flag。==(只在汇集索引上标记,若是查询的数据能够经过覆盖索引获取那么不就能查询出已删除的数据?)==
- innodb中有个history列表,它根据事物提交的顺序将undo log连接起来,先提交的事物总在尾端。
- purge先从history中找到第一个须要被清理的记录,清理后将对该undo log页所在的其余事物进行清理,若是还被别的事物占用则跳过。该页清理完成则继续从history中找下一个。
innodb_purge_batch_size
设置每次purge清理的undo页数,若是值太大则会致使CPU和磁盘IO过于集中。
- 当history list长度达到限制后,其会延缓DML操做。
group commit
- group commit指一次fsync能够刷新确保多个事物日志被写入文件。
- 开启二进制日志后,为了保证存储引擎层中的事物和二进制日志的一致性,两者之间使用两阶段事物。
- 事物提交时Innodb进行prepare操做。
- mysql数据库上层写入二进制日志。
- Innodb将日志写入redo log file,先修改内存中事物对应的信息并将其写入日志缓冲,然后调用fsync。
- 为了保证二进制日志与Innodb事物提交顺序一致,使用
prepare_commit_mutex
锁,这将致使group commit失效。
- 为了支持group commit Mysql5.6使用Binary Log Group Commit(BLGC)。
- 在Mysql数据库的上层进行提交时先按照顺序将其放入一个队列,第一个事物成为leader其他为follower,步骤以下:
- Flush阶段,将每一个事物的二进制日志写入内存中。
- Sync阶段,将内存中二进制日志刷到磁盘,若队列含有多个事物则仅一次fsync完成日志刷入
- Commit阶段,leader根据顺序调用存储引擎层的事物提交。
分布式事物
- Innodb支持XA事物,在使用分布式事物时须要使用Serializable的隔离级别。使用两阶段提交。
- XA事物由资源管理器(Resource Managers)、事物管理器(Transaction Manager)和应用程序(Application Program)组成。
欢迎关注本站公众号,获取更多信息