3. InnoDB日志 3.1 InnoDB架构
分为
内存区域架构
buffer pool
log buffer
磁盘区域架构
redo log
undo log
2.1.1 内存区域架构 1)Buffer Pool
定义
InnoDB对会将磁盘中经常访问的数据所在的页存入Buffer Pool中以加快访问速度,这种操作称为预读,后续对磁盘上某条数据做修改时,也是先读取到buffer pool中,再修改buffer pool中的数据
组成
由多个Page组成,其中存储了磁盘上的多行数据,方便了大容量的高效读操作,此外,将Page组织成链表结构,便于采用LRU进行内存淘汰
2)Change Buffer
定义
对于非唯一索引,如果在修改其对应的数据时,行记录不存在于Buffer Pool,那么就将修改操作记录到Change Buffer,等待后面真正读取到该记录到Buffer Pool中时,再将结果进行merge,并修改磁盘中的数据
为何必须非唯一
对于唯一索引,InnoDB需要对记录的唯一性做校验,也就必须从磁盘中读取到数据,而change buffer的存在意义是尽量避免不必要的随机磁盘io,而对于唯一性校验来说,磁盘io是不可避免的,且由于唯一索引b+树的特点,在是自增的情况下,插入操作是一次顺序io,效率是很高的,也就不必有change buffer
3)自适应哈希索引
定义
为了让MySQL性能更接近于基于内存的数据库,对于经常访问的数据,会根据数据的特点,以表的某几列建立hash索引,存储结构类似于hashmap,采用拉链法解决hash冲突,使得查询复杂度降低到O(1)
特性
优
适应等值比较
适应单条数据查询
劣
不适应范围查询
不可用范围或like比较
不适用连表查询
4)Log Buffer是磁盘上log文件的缓冲区,修改会先记录到此buffer,之后异步的同步到磁盘上的log文件
3.1.2 磁盘区域架构除了表、索引、表空间之外还有
1)Doublewrite Bufferbuffer pool中对页面的修改信息不会直接同步到对应的表中,而是会以大的连续块的形式调用fsync()写入到双写缓存中,这样在os、存储引擎或其他异常发生时,可以从双写缓存中找到备份
2)redo log 3)undo log 3.2 bin log&redo log&undo log 3.2.1 binlog 1)组成
binlog cache
作为binlog的缓存,会先写入cache中
binlog-xxx
存在于磁盘上的binlog文件,是append only式创建
2)存储内容可以配置成三种类型
statement
记录为逻辑日志,存储提交的事务的DML语句和事务号
row
记录为物理日志,记录了实际的修改,会使得日志比较大
mixed
前两者的结合
3)作用多用于主从同步和冷备
4)层级位于MySQL server层
3.2.2 redo log 1)组成
redo log buffer
作为redo log的缓存,会先写入cache中
ib_logfile-xxx
存在于磁盘上的redo log文件,是循环写入的,对于已经提交的事务,会清空
2)存储内容是物理日志和逻辑日志的结合,物理体现在记录了具体某一页上发生了修改,逻辑体现在页内的实际修改是以记录DML语句完成的
3)作用用于宕机恢复,保证一致性
4)层级位于存储引擎层
3.2.3 undo log 1)组成
undo log
update log
对于未提交的事务内发生的update操作,会存储相反的update
insert log
对于未提交的事务内发生的delete操作,会存储对应的insert
delete log
对于未提交的事务内发生的insert操作,会存储对应的delete
上述log会以事务号的顺序编排成一个链表以便于确定要回滚到哪个事务
2)存储内容是逻辑日志,存储相反的DML语句
3)作用用于回滚,保证原子性
4)层级位于存储引擎层
3.3 事务内修改流程假设事务内存在一条insert语句,那么实际执行流程如下
导入buffer并修改
记录undo log
记录redo log buffer并写盘
2PC提交
详细流程如下
3.3.1 导入buffer并修改检查buffer pool中是否存在要更新的数据所在的页,如果不存在,需要将页面读入buffer pool,之后修改对应的数据
3.3.2 记录undo log将delete语句记录到磁盘中的undo log,组织成链表
3.3.3 记录redo log buffer并写盘将修改记录到buffer,之后根据写盘策略,将buffer中的数据写入到redo log,同步的策略有下面三种,通过设定innodb_flush_log_at_trx_commit完成
0
每次提交都写入redo log buffer,之后每秒执行fsync()同步到redo log
1
每次提交都直接写入到redo log中
2
每次提交写入os cache,之后根据innodb_flush_log_at_timeout配置,决定多久后fsync()
3.3.4 2PC提交 1)流程