Mysql-事务


数据库引入事务的主要目的

事务会把数据库从一种状态转换为另一种一致的状态,在提交工作时,可以确保要么所有修改都已经保存,要么都不保存。

ACID特性

  • 原子性 atomicity

    要么都成功,要么都失败。

  • 一致性 consistency

  • 事务执行前后,数据库的完整性约束没有破坏。(你的10张银行卡里共有100块,无论这10张银行卡之间怎么转账,也只有100块)

  • 隔离性 isolation

    一个事务的影响在事务提交前,其他事务都不可见。

  • 持久性 durability

    事务一旦提交,就是永久性的。

事务的实现

redo

事务通过重做(redo)日志文件和日志缓冲(InnoDB Log Buffer)实现。在写数据前,需要先写日志。这种实现方式称为预写日志方式(Write-Ahead Logging,WAL)

  • 当开始一个事务时,会记录该事务的一个LSN(Log Sequence Number,日志序列号);

  • 当事务执行时,会往InnoDB存储引擎的日志缓冲里插入事务日志;

  • 事务提交是,必须将InnoDB存储引擎的日志缓冲写入磁盘。

    通过预写日志的方式保证事务的完整性,会造成吸盘上存储的数据页和内存缓冲池中的页是不同步的。可以通过show engine innodb status;查看当前磁盘和日志的差距。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    show engine innodb status\G;

    ---
    LOG
    ---
    Log sequence number 77292702 # 当前LSN
    Log flushed up to 77292702 # 刷新到重做日志文件的LSN
    Pages flushed up to 77292702
    Last checkpoint at 77292702 # 刷新到磁盘的LSN
    0 pending log writes, 0 pending chkp writes
    8 log i/o's done, 0.00 log i/o's/second

undo

事务需要回滚,需要undo。undo与redo正好相反,对于数据库进行修改是,数据库不但会产生redo,还会产生一定量的undo。

redo存放在重做日志中,undo存放在数据库内部的一个特殊段(segment)中,称为undo段(undo segment),undue段位于共享表空间中。

undo用于将数据库逻辑的恢复到原来的样子,数据结构本身在回滚前后可能不是相同的。

事务常用控制语句

  • begin
  • commit
  • rollback

事务的隔离级别

  • 读未提交 read uncommitted

    浏览访问

  • 读已提交 read committed

    游标稳定,生产上常用隔离级别

  • 可重复度 repeatable read

    InnoDB默认隔离级别,InnoDB在该级别下使用next-key锁的算法避免幻读的产生。

  • 序列化 serializable

    InnoDB会对每个select操作自动添加lock in share mode,即共享锁。因为InnoDB在rr的隔离级别就可以避免幻读,所以serializable隔离级别主要用于分布式事务。

查看事务隔离级别

1
2
select @@tx_isolation\G;
select @@global.tx_isolation\G;

分布式事务

分布式事务由一个或多个资源管理器、一个事务管理器和一个应用程序组成。

分布式事务使用两段式提交two-phase commit的方式。在第一个阶段,所有参与全局事务的节点都开始准备,告诉事务管理器他们准备好了。第二阶段,事务管理器告诉所有资源管理器执行rollback还是commit。如果任何节点显示不能提交,则所有节点都被告知需要回滚。

  • 资源管理器

    提供访问事务资源的方法。通常一个数据库就是一个资源管理器。

  • 事务管理器

    协调参与全局事务中的各个事务。需要合参与全局事务中的所有资源管理器进行通信。

  • 应用程序

    定义事务的边界,置顶全局事务中的操作。


  目录