Mysql事务以及其实现

    • 原子性:
    • 持久性
    • 隔离性
    • 一致性
    • 总结
    • undo log
    • redo log
    • redo log与binlog
    • 影响:
    • 隔离级别
    • 解决
    • 影响:
    • 解决
    • 写对写:
    • 写对读:


事务是一种规范,满足ACID四个特性. MySQL为了满足这四种特性做了大量的工作 。认识这些原理,对我们理解MySQL有很大的帮助。

原子性:

一个操作要么全部执行,要么全部不执行.

undo log

要保证事务的原子性,就要在异常发生时, 对已经执行的操作进行回滚. MySQL通过回滚日志(undo log)来记录sql执行相关信息,从而保证事务的原子性.。事务在进行操作的时候,先记录在回滚日志中, 然后在对数据库行进行操作。当需要回滚时,执行一条与回滚日志逻辑上相反的操作.

这种日志是逻辑上的日志 .

持久性

一旦事务被提交, 那么数据一定被写入到数据库中并持久化存储起来

redo log

重做日志(redo log): 同原子性一样, 事务的持久性也是通过日志来实现的.这种日志是物理上的日志,记录的是物理数据页面的修改信息. 重做日志在事务开始后就产生redo log.在对应的事务脏页写入磁盘后, redo log使命完成.

redo log与binlog

层次不同:redo log是InnDB引擎层面的。 binlog是服务器层面的

内容不同:redo log是物理日志, 内容基于磁盘的Page; binlog内容是二进制。记录过程。

隔离性

原子性,持久性侧重于研究事务本身.隔离性则侧重于研究不同事务之间的相互影响.

隔离性解决的是事务与事务之间相互影响的问题.
事务与事务之间可分为两种情况:
一个事务写操作对另一个事务写操作的影响: 可以通过锁机制保障写与写隔离性
一个事务写操作对另一个事务读操作的影响: MVCC保障写与读的隔离性

写对写:

影响:

隔离性要求同一时刻只能有一个事务对数据进行写操作

解决

InnoDB通过锁机制来解决写对写的问题。 InnoDB支持表锁与行锁。:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

出于性能考虑。 大部分都是使用过的行锁。

写对读:

影响:

脏读:读事务读到了写事务未提交的数据
不可重复读:读事务内同两次读取同一个数据,两次结果不一样.写事务在读前后修改了数据
幻读**:读事务**内按照某个条件两次查询的结果不同,写事务在读前后改变了数据条数

隔离级别

这些影响按照可以容忍的程度, 划分了4个隔离级别

读未提交:最低级别的隔离级别, 可以容忍上述三种影响

读已提交:不能容忍脏读的出现

可重复读(RR):不能容忍脏读,不可重复读。 可以容忍幻读的出现

可串行化:三种情况都不容忍。

解决

InnDB使用MVCC(多版本控制协议),next-key lock解决了脏读,不可重复读, 幻读问题.

InnDB默认的隔离级别是RR,在SQL标准中,RR是无法避免幻读问题的. 但是InnDB实现的RR却避免了幻读问题.

  • MVCC特点是读不加锁,并发性能好.多个版本的共存,主要依靠数据的隐藏列(类CAS)和undo log
  • next-key lock是行锁的一种,实现相当于record lock(记录锁) + gap lock(间隙锁);其特点是不仅会锁住记录本身(record lock的功能),还会锁定一个范围(gap lock的功能)

InnoDB的RR隔离级别下:

  • 脏读使用undo log来解决.
  • 不可重复读使用:版本号+undo log来解决
  • 幻读使用: next-key lock来解决

一致性

一致性是事务执行结束后,一致性是事务追求的最终目标. 当我们前面提到的原子性,持久性,隔离性都做到时,一致性也基本可以保障了.

总结

原子性:要么执行,要么不执行。实现基于undo log

持久性: 保证事务提交后不会因宕机等原因导致数据丢失, 实现主要基于redo log

隔离性: 保证事务与事务之间尽量不影响。 InnoDB默认的隔离级别是RR, RR主要实现基于锁机制(写对写);数据隐藏列,undo log 类next-key lock机制(写对读)

一致性:事务的最终目标