手记

MySQL随笔03_事务隔离

一、什么是事务

简单来说,事务就是要保证一组数据操作,要么全部成功,要么全部失败。

在MySQL中,事务支持是在引擎层实现的。MySQL是一个支持多引擎的系统,但并不是所有引擎都支持事务。

二、事务的基本特性

事务的四大基本特性:原子性、一致性、隔离性、持久性,即大名鼎鼎的 ACID

原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

三、隔离性与隔离级别

对于事务的隔离级别,隔离得越严格,效率就会越低。 因此,很多时候需要在二者之前寻找平衡点。

事务隔离级别概念来源

当数据库上有多个事务同时执行时,就可能出现 脏读不可重复读幻读 的问题,由此产生隔离级别的概念。

读现象
  • 脏读——是指当前事务读取另一个事务修改的数据,但是另一个事务对这些数据做了回滚,或者在提交前再次更新,而这些数据可能被当前事务用户后续的处理中。

    只有在读未提交(READ-UNCOMMITTED)隔离级别下才可能出现脏读。

  • 不可重复读——在一个事务中,前后相同的两次查询,结果应当是一样的,但是查询的返回结果确不一致。

  • 幻读——某一行出现在一次查询的结果集中,但是没有出现在之前该查询的结果集中。

SQL标准的事务隔离级别
  1. 读未提交 指一个事务还没提交时,它做的变更就能被别的事务看到。
  2. 读提交 指一个事务提交后,它做的变更才能被其他事务看到。
  3. 可重复读 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。在此隔离级别下,未提交变更对其他事务也是不可见的。
  4. 串行化 对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。 当出现读写冲突时,后访问的事务阻塞,必须等前一个事务执行完成才能继续执行。

假设一个只有一个字段的表T,有一条记录字段值为1。两个事务A、B在不同隔离级别下查询到的值,如下图。




在实现上,数据库内部会创建一个视图,访问时以视图的逻辑结果为准。(此视图与我们常规使用的视图不是同一个)

注意点:

  1. 读未提交 隔离级别,直接返回记录上最新的值,没有视图的概念。
  2. 串行化 隔离级别,直接用加锁的方式避免并行访问可能发生的问题。
MySQL设置隔离级别参数

MySQL配置隔离级别是通过启动参数 transaction-isolation 来设置的。可选值如下:

  • READ-UNCOMMITTED 读未提交
  • READ-COMMITTED 读提交
  • REPEATABLE-READ 可重复读 (默认值)
  • SERIALIZABLE 串行化

四、事务隔离的实现——MVCC

在MySQL中,每条记录在更新的时候都会同时记录一条回滚操作。记录上最新的值,通过回滚操作,都可以得到前一个状态的值。

在并行的多事务环境下,不同时刻启动的事务有不同的 read-view,同一条记录在系统中可以存在多个版本,即数据库的多版本并发控制 MVCC

回滚日志清理时机

系统判断当没有事务再需要用到回滚日志时则删除。

当系统中没有比这个回滚日志更早的 read-view 时,就不需要回滚日志了。

尽量不要使用长事务

使用长事务使得系统中会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何书籍,所以在该事务提交之前,数据库里它可能用到的回滚记录都必须保留,从而导致大量占用存储空间。除此之外,长事务还占用锁资源,可能拖垮整个库。

即使用长事务可能存在的问题:

  1. 大量占用存储空间
  2. 占用锁资源

五、事务的启动方式

MySQL 事务启动方式:

  1. 显示启动事务语句。 begin/start transaction---->commit/rollback。

  2. set autocommit=0或1,此命令表示将线程的自动提交关闭开启

    autocommit=0 时,执行一个select事务就启动了,但不会自动提交,只有主动执行commitrollback断开连接时才会提交。

    autocommit=1 时 (建议设置),用begin显示启动事务,若执行commit则提交事务。

关于”多一次交互“问题

在设置了autocommit=1情况下,对于一个需要频繁使用事务的业务,每一次都多一个begin显示启动事务的交互,可使用commit work and chain语法,表示提交事务并自动开启下一个事务。

  1. 减少交互次数。
  2. 较少再次执行begin语句的开销。

六、小结

本文由博客一文多发平台 OpenWrite 发布!

0人推荐
随时随地看视频
慕课网APP