有时候我们要确保几个操作是原子操作,就需要使用到事务,比如转账行为。
在MySQL中,事务是在引擎层支持的。但不是所有的引擎都支持事务,原生的MyISAM就不支持事务,所以也是被InnoDB所取代的一个原因。

隔离性与隔离级别

事务的ACID特性中的I(Isolation),是指隔离性,当数据库有多个事务同事执行时,可能会出现下面几个问题:

  1. 脏读,dirty read:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是 脏数据,依据脏数据所做的操作可能是不正确的。
  2. 不可重复读,non-repeatable read:在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。
  3. 幻读,phantom read

为了解决这些问题,有了「隔离级别」的概念,SQL标准的隔离级别有:

  1. 读未提交:一个事务还没提交时,它做的变更就能被别的事务看到;
  2. 读提交:一个事务提交后,它做的变更才能被其他事务看到;
  3. 可重复读:一个事务执行过程中,它看到的数据总是一致的。未提交的变更对其他事务不可见;
  4. 串行读:「读」会加「读锁」,「写」会加「写锁」,当出现读写锁冲突时,后面事务需要等待前面的事务完成,才能继续执行。

事务隔离的实现

MySQL中的「可重复读」,在每条记录更新时,都会记录一条回滚操作。记录上最新的值都可以通过回滚得到以前状态的值。
每个事务启动的时候,都会有不同的read-view,它们看到的值都是可以不同的。

回滚日志什么时候会被清除?
不需要的时候才会被删除,就是当系统里没有比这个回滚日志更早的read-view的时候。

长事务意味着系统会存在很老的事务视图,在事务被提交前,它可能用到的回滚记录都必须保留,导致占用大量存储空间。

参考

「极客时间」-「MySQL实战45讲」