MySQL中的事务由存储引擎实现,支持事务的存储引擎不多,本文主要了解InnoDB存储引擎中的事务。
事务处理用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
事务用来管理DDL、DML、DCL 操作,如insert,update,delete 语句,默认是自动提交的。
一、事务ACID特性
Atomicity 原子性,构成事务的所有必须是一个逻辑单元,要么全部执行,要么全部不执行(失败);
Consistency 一致性,数据库在事务执行前后状态都必须一致的或稳定的;
Isolation 隔离性,事务之间不会相互影响;(由锁机制和MVCC机制实现,MVCC多版本并发控制,优化读写性能,读不加锁、读写不冲突);
Durability 持久性,事务执行成功后必须全部写入磁盘;
二、事务开启/提交
-
BEGIN 或START TRANSACTION显式地开启一个事务;
-
COMMIT (COMMIT WORK)提交事务,使已对数据库进行的所有修改成为永久性;
-
ROLLBACK(ROLLBACK WORK)回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
三、InnoDB
1.InnoDB架构图
上图详细显示了InnoDB存储引擎的体系架构,从图中可见,InnoDB存储引擎由内存池,后台线程和磁盘文件三大部分组成。
2.InnoDB内存结构
2.1 Buffer Pool缓冲池
InnoDB采用缓存机制来实现提升处理数据的效率,Buffer Pool就是执行缓存区域;
Buffer Pool中包含data page数据页、index page索引页、insert buffer page插入缓冲页、adaptive hash index自适应哈希(热点哈希)、lock info锁信息、data dictionary数据字典; Page(页)是Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位;执行增删改时,缓存里的数据页和磁盘里的数据页不一致,该数据页为脏页; 插入缓冲(Insert Buffer)是单独对于插入操作的执行缓存区,其原因在于执行插入操作相对复杂度高,要进行主键排序、索引树、插入算法等等,需要单独缓冲区; 自适应哈希索引(Adaptive Hash Index)的结构是hash结构,即key-value,InnoDB会根据访问频率,来为热点页建立哈希索引,来提升查询的效率(将访问频率高的从B+TREE上取出再建立一个k-v结构的哈希索引); 锁信息(lock info),存放行锁、 表锁等锁的信息; 数据字典信息(Data Dictionary)中存放元数据信息,包括表结构、数据库名、表名、字段的数据类型、视图、索引、表字段信息、存储过程、触发器等内容;
2.2 Redo log Buffer重做日志缓冲
Redo Log https://www.jianshu.com/p/d13b3c98ce30
Redo Log 机制,如果要存储数据则先存储数据的日志 ,目的是为保障一旦内存崩溃则可以从日志找修改的记录;重做日志保证了数据的可靠性,InnoDB采用了Write Ahead Log(预写日志)策略,即当事务提交时,先写重做日志,然后再择时将脏页写入磁盘,如果发生宕机导致数据丢失,就通过重做日志进行数据恢复;落盘成功后清除Redo Log File内容。
Redo Log File是mysql默认创建的文件,在mysql目录中有两个文件即ib_logfile0、 ib_logfile1,Redo Log File默认为8MB可通过配置参数innodb_log_buffer_size来调整文件大小;
2.3重做日志的落盘机制
Force Log at Commit机制实现事务的持久性,即当事务提交时,必须先将该事务的所有日志写入到重做日志文件进行持久化,然后事务的提交操作完成才算完成;为了确保每次日志都写入到重做日志文件,在将重做日志缓冲写入重做日志文件过程中,必须调用一次fsync操作(操作系统,最终实现持久化一定是有操作系统完成),将缓冲文件从文件系统缓存(OS Buffer)中真正写入磁盘。
可以通过innodb_flush_log_at_trx_commit 来控制重做日志刷新到磁盘的策略,共有0、1、2三个参数值;参数默认值为1,表示事务提交必须进行一次fsync操作;0表示事务提交时不进行写入重做日志操作,该操作只在主线程中完成;2表示提交时写入重做日志,但是只写入文件系统缓存,不进行fsync操作;由此可见,设置为0时,性能最高,但是可能造成数据丢失,无法保障事务的一致性。
Double Write双写机制
Double Write带给InnoDB存储引擎的是数据页的可靠性;
如上图所示,Double Write由两部分组成,一部分是内存中的double writebuffer,大小为2MB,另一部分是物理磁盘上共享表空间连续的128个页,大小也为2MB;在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是通过memcpy函数将脏页先复制到内存中的double write buffer区域,之后通过double write buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免操作系统缓冲写带来的问题;完成double write页的写入后,再将double wirite buffer中的页写入各个表空间文件中,如果操作系统在将页写入磁盘的过程中发生了崩溃,恢复过程时,InnoDB存储引擎可以从共享表空间中的double write中找到该页的一个副本,将其复制到表空间文件中,再应用RedoLog重做日志。
CheckPoint检查点(择时) 检查点,表示脏页写入到磁盘的时机,所以检查点也就意味着脏数据的写入。 -- checkpoint作用
-
缩短数据库的恢复时间
-
buffer pool空间不够用时,将脏页刷新到磁盘
-
redolog不可用时,刷新脏页
--检查点分类
-
1、sharp checkpoint完全检查点
数据库正常关闭时,会触发把所有的脏页都写入到磁盘上
-
2、fuzzy checkpoint模糊检查点(正常使用时)
部分页写入磁盘,分为以下四种; -1- master thread checkpoint(定时) :以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘,这个过程是异步操作; -2- flush_lru_list checkpoint : 读取lru (Least Recently Used-最近最少使用) list列表,找到脏页,写入磁盘; -3- async/sync flush checkpoint :log file快满了,会批量的触发数据页回写,这个事件触发的时候又分为异步和同步,不可被覆盖的redolog占log file的比值:75%异步写、90%同步写。 -4- dirty page too much checkpoint :默认是脏页占比75%的时候,就会触发落盘,将脏页写入磁盘;
3.InnoDB磁盘文件
系统表空间和用户表空间
重做日志文件和归档文件
ib_logfile0 和 id_logfile1在日志组中每个重做日志文件的大小都是一致的,并以【循环写入】的方式运行;
InnoDB存储引擎先写入重做日志文件ib_logfile0,当文件被写满时会切换,写入 id_logfile1,切换后ib_logfile0会被清空(落盘),当id_logfile1文件被写满时再切换,写入 id_logfile0。