MySQL-事务总结

一、含义:是数据库操作的最基本单元,是一组不可再分的DML操作,要么同时成功,如果有一个DML操作失败则全部操作失败。

二、事务具有原子性、一致性、隔离性、持久性(ACID)。

  • 原子性:事务不可再分割,是最小单位。要么同时成功,要么同时失败。
  • 一致性:事务执行前后,使数据从一个合法状态转化为另一种合法状态,合法状态指数据符合业务逻辑。
  • 隔离性:多个事务并发执行,彼此之间互不影响。
  • 永久性:事务一旦提交,则对数据库的修改是永久性的。

三、事务的开启

  • BEGIN或START TRANSACTION

四、事务的提交与回滚

  • autocommit为ON时,DML操作默认自动提交。
  • DDL和DCL操作自动提交。
  • DML操作执行完后,仅修改内存中的记录,需要执行COMMIT把redo日志刷盘,而在内存中的脏页则由MySQL决定何时进行刷盘操作。(注:事务中的每个DML执行完后都会往redo日志缓存中写入redo日志,每个DML执行前直接往undo日志缓存中写入undo日志)
  • ROLLBACK:回退该事务之前的操作。

五、事务并发时产生的问题与隔离级别

  • 脏写:事务A修改了一条记录,但没有COMMIT,事务B也修改了该条记录,随后事务A ROLLBACK,事务B则COMMIT,则发现记录没有被修改。(注:MySQL所有隔离级别均不允许脏写出现)
  • 脏读:事务A修改了一条记录,但没有COMMIT,随后事务B读取了该条记录,然后事务A ROLLBACK,则读取了不存在的记录。
  • 不可重复读:事务A按条件读取了一些记录,随后事务B删除或修改了事务A读取出来的全部或部分记录并COMMIT,事务A再次按照前面的条件读取记录,发现部分记录被修改或删除。(在查询条件相等的两次查询中,查询出来的结果不一致)
  • 幻读:事务A按条件读取了一些记录,随后事务B插入一些新记录并COMMIT,事务A再次按照前面的条件读取记录,发现多出了事务B插入的新记录。(在查询条件相等的两次查询中,第二次查询的结果出现了在第一次查询中不存在的记录)
SHOW VARIABLES Like 'TRANSACTION_ISOLATION'; #查看隔离级别

#不支持脏写
SET @@SESSION.TRANSACTION_ISOLATION = 'READ-UNCOMMITTED';

#不支持脏写、脏读
SET @@SESSION.TRANSACTION_ISOLATION = 'READ-COMMITTED';

#不支持脏写、脏读、不重复读、幻读(MySQL在该隔离等级利用间隙锁解决幻读问题)
SET @@SESSION.TRANSACTION_ISOLATION = 'REPEATABLE-READ';

#不支持脏写、脏读、不重复读、幻读
SET @@SESSION.TRANSACTION_ISOLATION = 'SERIALIZABLE';

###注意:越往下隔离级别越高,但事务并发性越差

注:MySQL默认的隔离级别是REPEATABLE-READ。

六、redo日志

  • redo日志是物理日志,记录了某个页面的某个偏移量处修改了什么内容(物理磁盘的变化),维护底层B+树的结构。

  • 作用:保证了事务的持久性。 当事务COMMIT后,在内存中的脏页不是立即写入磁盘中,而是由MySQL决定何时进行刷盘操作。如果在脏页刷盘前MySQL崩溃,那么在内存中的脏页数据就会丢失,数据库中的数据就和业务不一致,违反了事务的持久性。此时需要保证WAL(WRITE AHEAD LOG),在COMMIT后把redo日志进行刷盘操作。就算脏页在刷盘前发生数据库崩溃,在MySQL重启后读取redo日志中的数据即可把未成功刷盘的脏页写入磁盘。

  • 为什么MySQL不直接把COMMIT后的脏页写入磁盘? (1)一个页默认16KB,当一个事务仅修改一个页中的几个B的数据就把脏页刷盘,这十分浪费。(2)如果一个事务修改了涉及多个页的数据,而这些页存储在磁盘上相隔较远的位置,那么就需要进行大量的随机IO,时间消耗较大。

  • redo日志记录了什么? redo日志记录了表空间ID、页号、偏移量、修改的内容。
    补充: 对底层页面的一次原子访问的过程称为Mini-Transaction (MTR),一个MTR可以包含若干条redo日志。如一条记录插入后,需要修改多个B+树(修改一棵树时,访问这棵树中对应的一个页面,为1个MTR;但修改了多棵树,为多个MTR),但一棵树中可能出现页分裂、页内的记录迁移、页头信息修改等(多个redo log)。一个事务可以包含多个DML,而一个DML可以涉及多条记录的变更,所以一个DML可以包含多个MTR。
    MySQL-事务总结_第1张图片

  • redo日志的刷盘机制MySQL-事务总结_第2张图片
    注:值为1时可以保证事务的持久性,但在数据量大的情况下,会出现频繁的随机IO,所以时间花费1>0=2。

  • redo日志是顺序IO来写入。

  • checkpoint、write pos
    (1)checkpoint:每次加载redo日志来重新写入COMMIT后未刷盘的数据时,会清空刷盘成功的日志,并将其后移。
    (2)write pos:记录redo日志当前记录的位置,一边写一边后移。
    MySQL-事务总结_第3张图片
    注:checkpoint和write pos右边空白处是等待用于恢复COMMIT后未刷盘的日志,左边空白处则是等待写入日志的空间。

七、undo日志

  • undo日志是逻辑日志。记录的是SQL语句,如事务中执行的DML操作是insert,则对应的SQL语句是delete,如执行的是delete,则对应的SQL语句是insert,如执行的是update,则对应的SQL语句是update成执行前的状态。
  • 作用:保证了事务的原子性。 实现事务的ROLLBACK及MVCC。
  • undo log会产生redo log,undo log的产生会使行记录头信息中的回滚指针发生改变,所以需要redo log记录某个页面的某个偏移量处修改了什么内容,维护底层B+树的结构
  • 回滚段与页:
    (1)一个回滚段有1024个undo log segment。
    (2)Innodb1.1前,只有一个回滚段,支持并发事务的数量是1024。
    (3)Innodb1.1及以后,有128个回滚段,支持并发事务的数量是128*1024。
  • undo页的重用:一个undo页可能会混有其他事务的undo log。

你可能感兴趣的:(mysql,mysql)