【Mysql分享】之事务分析篇

目录索引
【Mysql分享】之索引篇
【Mysql分享】之锁篇
【Mysql分享】之事务分析篇

事务介绍

在MySQL中的事务是由存储引擎实现的,而且支持事务的存储引擎不多,主要分享InnoDB存储引擎中的事务。
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。 事务用来管理 DDL、DML、DCL 操作,比如 insert,update,delete 语句,默认是自动提交的。

事务四大特性(ACID)

  • Atomicity(原子性):构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不
    执行。
  • Consistency(一致性):数据库在事务执行前后状态都必须是稳定的或者是一致的。
  • Isolation(隔离性):事务之间不会相互影响。由锁机制和MVCC机制来实现的 MVCC(多版本并发控制):优化读写性能(读不加锁、读写不冲突)
  • Durability(持久性):事务执行成功后必须全部写入磁盘。

Innodb架构图

在这里插入图片描述

InnoDB存储引擎由内存池,后台线程和磁盘文件三大部分组成

Buffer Pool缓冲池

Buffer Pool:(innodb_buffer_pool_size)设置缓存池大小。 缓冲池是InnoDB在启动时分配的一个内存区域, 是以Page页为单位,默认大小16K,用于InnoDB在访问数据时缓存表和索引数据。 利用缓冲池, 可以合并一些对经常访问的数据的操作, 直接从内存中处理,减少磁盘IO操作,提升效率。Buffer Pool的底层采用链表数据结构 +LRU(最近最少使用) 算法管理Page。

数据页和索引页: Page是Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位做增删改时缓存里的数据页和磁盘里的数据页不一致,该数据页为脏页

插入缓冲(Insert Buffer): 作用减少磁盘的离散读取,将多次插入合并为一次操作,对于非聚集类索引的插入和更新操作,不是每一次都直接插入到索引页中,而是先判断插入的非聚集索引叶子是否在缓冲池中,若在,则直接插入;若不在,则先将插入的记录放到insert buffer中,然后根据一些算法将insert buffer 缓存的记录通过后台线程慢慢的合并(merge)回辅助索引页中。

自适应哈希索引(Adaptive Hash Index): InnoDB会根据访问的频率和模式,为热点页建立哈希索引,来提高查询效率,

锁信息(lock info): 行锁、 表锁 …

数据字典信息(Data Dictionary): 元数据信息 包括表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、存储过程、触
发器等内容

Redo log Buffer重做日志缓冲

重做日志: Redo Log 如果要存储数据则先存储数据的日志 , 一旦内存崩了则可以从日志找,重做日志保证了数据的可靠性,InnoDB采用了Write Ahead Log(预写日志)策略,即当事务提交 时,先写重做日志,然后再择时将脏页写入磁盘。如果发生宕机导致数据丢失,就通过重做日志进行数 据恢复。
insert into xxxx
commit; Redo Log File 写成功 则Commit;
Redo Log : ib_logfile0 ib_logfile1 默认为8MB。 可通过配置参数 innodb_log_buffer_size 控制

在这里插入图片描述

Force Log at Commit机制

实现事务的持久性,即当事务提交时,必须先将该事务的所有日志写入到重 做日志文件进行持久化,然后事务的提交操作完成才算完成。为了确保每次日志都写入到重做日志文 件,在每次将重做日志缓冲写入重做日志后,必须调用一次fsync操作(操作系统),将缓冲文件从文 件系统缓存中真正写入磁盘。
innodb_flush_log_at_trx_commit 该参数默认值为1
重做日志的落盘机制

在这里插入图片描述

可以通过 innodb_flush_log_at_trx_commit 来控制重做日志刷新到磁盘的策略。该参数默认值为 1,表示事务提交必须进行一次fsync操作,还可以设置为0和2。0表示事务提交时不进行写入重做日志 操作,该操作只在主线程中完成,2表示提交时写入重做日志,但是只写入文件系统缓存,不进行fsync 操作。由此可见,设置为0时,性能最高,但是丧失了事务的一致性。

Double Write双写

Double Write带给InnoDB存储引擎的是数据页的可靠性
在这里插入图片描述

如上图所示,Double Write由两部分组成,一部分是内存中的double write buffer,大小为2MB,另一部分是物理磁盘上共享表空间连续的128个页,大小也为2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是通过memcpy函数将脏页先复制到内存中的double write buffer区域,之后通过double write buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免操作系统缓冲写带来的问题。在完成double write页的写入后,再讲double wiritebuffer中的页写入各个表空间文件中。如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,InnoDB存储引擎可以从共享表空间中的double write中找到该页的一个副本,将其复制到表空间文件中,再应用重做日志.

CheckPoint: 检查点

表示脏页写入到磁盘的时机,所以检查点也就意味着脏数据的写入。

checkpoint的目的
  • 缩短数据库的恢复时间
  • buffer pool空间不够用时,将脏页刷新到磁盘
  • redolog不可用时,刷新脏页
检查点分类
  1. sharp checkpoint: 完全检查点 数据库正常关闭时,会触发把所有的脏页都写入到磁盘上
  2. fuzzy checkpoint: 正常使用时 模糊检查点,部分页写入磁盘。
  3. master thread checkpoint : 以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁 盘,这个过程是异步的,
  4. flush_lru_list checkpoint : 读取lru (Least Recently Used) list,找到脏页,写入磁盘。 最近最少使用
  5. async/sync flush checkpoint : redo log file快满了,会批量的触发数据页回写,这个事件触发的时候 又分为异步和同步,不可被覆盖的redolog占log file的比值:75%—>异步、90%—>同步。
  6. dirty page too much checkpoint : 默认是脏页占比75%的时候,就会触发刷盘,将脏页写入磁盘

Innodb磁盘文件

innodb_data_file_path 的格式如下: innodb_data_file_path=datafile1[,datafile2]…

用户可以通过多个文件组成一个表空间,同时制定文件的属性: innodb_data_file_path=/db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend
这里将/db/ibdata1和/dr2/db/ibdata2两个文件组成系统表空间

系统表空间(共享表空间)

1、数据字典(data dictionary):记录数据库相关信息
2、doublewrite write buffer:解决部分写失败(页断裂)
3、insert buffer:内存insert buffer数据,周期写入共享表空间,防止意外宕机
4、回滚段(rollback segments)
5、undo空间:undo页

用户表空间(独立表空间)

1、每个表的数据和索引都会存在自已的表空间中
2、每个表的结构
3、undo空间:undo页 (需要设置)
4、doublewrite write buffer

重做日志文件和归档文件

ib_logfile0 和 ib_logfile1 在日志组中每个重做日志文件的大小一致,并以【循环写入】的方式运行。InnoDB存储引擎先写入重做日志文件1,当文件被写满时,会切换到重做日志文件2,再当重做日志文件2也被写满时,再切换到重做日志文件1。

Innodb事务分析

原子性,持久性和一致性主要是通过redo log、undo log和Force Log at Commit机制机制来完成的。redo log用于在崩溃时恢复数据,undo log用于对事务的影响进行撤销,也可以用于多版本控制(MVCC)。而Force Log at Commit机制保证事务提交后redo log日志都已经持久化。
开启一个事务后,用户可以使用COMMIT来提交,也可以用ROLLBACK来回滚。其中COMMIT或者ROLLBACK执行成功之后,数据一定是会被全部保存或者全部回滚到最初状态的,这也体现了事务的原子性。但是也会有很多的异常情况,比如说事务执行中途连接断开,或者是执行COMMIT或者ROLLBACK时发生错误,Server Crash等,此时数据库会自动进行回滚或者重启之后进行恢复。

redo log重做日志,每次数据库的SQL操作导致的数据变化它都会 记录一下,具体来说,redo log是物理日志,记录的是数据库页的物理修改操作。如果数据发生了丢失,数据库可以 根据redo log进行数据恢复。
在事务执行的过程中,除了记录redo log,还会记录一定量的undo log。undo log记录了数据在每个操作前的状态, 如果事务执行过程中需要回滚,就可以根据undo log进行回滚操作。

ReadView当前事务(读)能读哪个历史版本?
Read View是事务开启时当前所有事务的一个集合,这个类中存储了当前Read View中最大事务ID及最小事务ID。

查看事务列表
show engine innodb status

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX

在repeatable read的隔离级别下,创建事务trx结构的时候,就生成了当前的global read view。使用trx_assign_read_view函数创建,一直维持到事务结束。在事务结束这段时间内 每一次查询都不会重 新重建Read View , 从而实现了可重复读。

系列文章
【Mysql分享】之索引篇
【Mysql分享】之锁篇
【Mysql分享】之事务分析篇

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值