mysql事务的知识点

概述

事务 可由一条简单的sql组成,也可有一组复杂的sql组成,事务是访问访问并更新数据库中各种数据项的一个程序执行单元。在事务的操作中,要么都在修改要么都不做。这就是事务的目的,也是事务模型区别文件系统的重要特征之一。

mysql 架构图

25a34155827806ffe0a0267ef7b4ad4b.jpg

0f125be2bbe942f3bbb92352fab9b9c0.jpg

事务的特性

原子性(Atomicity):

作为逻辑工作单元,一个事务里的所有操作的执行,要么全部成功,要么全部失败。

一致性(Consistency):

数据库从一个一致性状态变换到另外一个一致性状态,数据库的完整性不会受到破坏。

隔离性(Isolation):

通常来说,一个事务所做的修改在最终提交前,对其他事务是不可见的。为什么是通常来说,为了提高事务的并发引出不同的隔离级别,具体参考下一章节。

持久性(Durability):

一旦事务提交,则其所做的修改就会永久保存到数据库中,即使系统故障,修改的数据也不会丢失。

mysql的日志文件

错误日志:

是对mysql的启动 运行 关闭过程进行了记录。

慢查询日志

可帮助定位可能存在的问题的sql语句。从而进行sql语言层面的优化。

查询日志

记录了所有对mysql数据库请求的信息,无论这些请求是否得到了正确的执行。

二进制日志

记录了对mysql数据库执行更改的所有操作,但不包含select 和show 这类操作。因为这类操作对数据库本身并没有修改。

InnoDB存储引擎日志文件
  • redo log : 重做日志,用来保证原子性和持久性,
  • undo log : 撤销日志,用来保证一致性

事务的实现 undo log和redo log

事务的自动提交

Mysql 默认采用自动提交(AUTOCOMMIT)模式,也就是说,如果不显示地开始一个事务,则每个查询都被当做一个事务执行提交操作。 可以通过以下命令查看 mysql 是否打开自动提交,

show variables like 'AUTOCOMMIT';

1、通过 set autocommit = 0 关闭当前会话的自动提交,如果需要对全局生效必须再配置文件中进行修改。

2、关闭自动提交后,用户的所有 DML 语句都会在同一个事务中,直到遇到 COMMIT 或 ROLLBACK 指令结束事务。

redo log

redo log分为2部分:

  • 重做日志缓冲区(redo log buffer),内存中,易丢失
  • 重做日志文件(redo log file),磁盘中,持久的。

redo log file 是顺序写入的,在数据库运行时不需要进行读取,只会在数据库启动的时候读取来进行数据的恢复工作。 redo log file 是物理日志,所谓的物理日志是指日志中的内容都是直接操作物理页的命令。重做时是对某个物理页进行相应的操作。

当mysql 发生宕机而操作系统不发生宕机当时候,并不会导致事务当丢失,而当操作系统发生宕机的时候,重启数据库会从文件系统缓存刷新到重做日志文件那部分事务。

更新事务操作一次数据的流程图如下所示:


a.png

第一步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝。

第二步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值。

第三步:在必要的时候,采用追加写的方式将 redo log buffer 中的内容刷新到 redo log file。

第四步:定期将内存中修改的数据刷新到磁盘中。

以上比较重要的是第三步,其中必要的时候有以下几种情况:

事务提交时(最常见的情景,在 commit 之前)
当 log buffer 中有一半的内存空间被使用时
log checkpoint 时
实例 shutdown 时
binlog切换时
后台线程

事务提交时将 redo log buffer 写入 redo log file,为了保证数据一定能正确同步到磁盘(不仅仅只写到文件缓冲区中)文件中,InndoDB 默认情况下调用了 fsync 进行写操作。而 fsync 的性能比较低。当然这只是默认情况,InnoDB 也提供了参数 innodb_flush_log_at_trx_commit 来配置 redo log 刷新到磁盘的策略,


b.png

上图可以更直观的说明 innodb_flush_log_at_trx_commit 不同值下的不同策略。操作越接近磁盘性能越低,当然可靠性越来越高。故性能:1 < 2 < 0,可靠性:0 < 2 < 1。

当 innodb_flush_log_at_trx_commit 设置为 0 或者 2 时丧失了事务的 ACID 特性,通常在日常环境时将其设置为 1,而在系统高峰时将其设置为 2 以应对大负载。

undo log

  1. undo log 用来实现事务的一致性,InndoDB 可以通过 redo log 对页进行重做操作。但是有时候事务需要进行回滚,这时就需要 undo log。
  2. undo log 还可可以用来协助 InnoDB 引擎实现 MVCC 机制。
  3. undo log 是逻辑日志,恢复时并不是对物理页直接进行恢复,而是逻辑地将数据库恢复到原来的样子。
  4. undo log 的产生也会伴随着 redo log 的产生。
写入对时机:
c.png

undo log有两个作用:提供回滚和多个行版本控制(MVCC)。
当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。

事务间的隔离

与原子性、持久性、一致性 侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响。隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。
隔离性追求的是并发情形下事务之间互不干扰。

锁机制

锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

  • 行锁和表锁
    按照粒度,锁可以分为表锁、行锁,例如MyIsam只支持表锁,而InnoDB同时支持表锁和行锁,且出于性能考虑,绝大多数情况下使用的都是行锁。
  • 共享锁和排他锁
    InnoDB 实现了标准的行级锁,包括两种:共享锁(简称 s 锁)、排它锁(简称 x 锁)。
    共享锁(S锁):允许持锁事务读取一行。
    排他锁(X锁):允许持锁事务更新或者删除一行。
隔离级别
aa.png

在实际应用中,读未提交在并发时会导致很多问题,而性能相对于其他隔离级别提高却很有限,因此使用较少。可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。因此在大多数数据库系统中,默认的隔离级别是读已提交(RC)(如Oracle)或可重复读(RR)。mysql 是 可重复读。

MVCC

RR解决脏读、不可重复读、幻读等问题,使用的是MVCC:MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。
它是通过读取历史版本的数据,来降低并发事务冲突,从而提高并发性能的一种机制。它的实现依赖于隐式字段、undo日志、快照读&当前读、Read View.


ss.png

MVCC最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要是依靠数据的隐藏列(也可以称之为标记位)和undo log。其中数据的隐藏列包括了该行数据的版本号、删除时间、指向undo log的指针等等;当读取数据时,MySQL可以通过隐藏列判断是否需要回滚并找到回滚需要的undo log,从而实现MVCC........

参考:
详细分析mysql事务日志
十分钟搞懂MySQL四种事务隔离级别
Mysql 事务-你想知道都在这
一文彻底读懂MySQL事务的四大隔离级别
脏读 幻读 不可重复度

你可能感兴趣的:(mysql事务的知识点)