MySQL 学习笔记 - 事务 & 锁

事务

第一个前提:事务是存储引擎层面支持的,InnoDB支持事务,MyISAM不支持事务。本文都是指的InnoDB。
第二个前提 :MySQL默认设置autocommit = on,即任何语句若没有显示地开启事务,都被当做一个独立的事务进行执行 —— Even a select statement opens a transaction

老生常谈,说起事务,就得先提一下事务的ACID特性

事务的ACID特性

  • 原子性 Atomicity
    事务里的操作要么全部成功,要么全部失败
  • 一致性 Consistency
    事务和数据约束的一致性,事务完成前后,都不能与数据本身的完整性约束相悖,例如唯一索引约束,表结构约束等等。
  • 隔离性 Isolation
    数据库应该具有并发事务同时对数据进行读写修改的能力。 --> 事务的四个隔离级别
  • 持久性 Durability
    事务处理后,数据的修改应该是永久的,系统挂了,也不会丢失。

事务的隔离级别

  1. 读未提交 Read uncommitted
    一个事务能读到另一个事务还没有提交的数据,会产生脏读
  2. 读提交 Read committed
    一个事务只能读到别的事务提交过后的数据,会不可重复读
  3. 可重复读 Repeatable read
    一个事务在事务进行的期间,同样的查询语句不同时刻查得到的结果应该是一样的,可能产生幻读(但是MySQL使用了next-key lock来解决)
  4. 串行化 Serializable
    不允许并发,一个数据只有被持有它的事务提交/回滚释放锁之后,才能被其他事务访问。

以上隔离级别由1-4,并发性能越来越差,隔离程度越来越深。InnoDB默认的隔离级别是可重复读,而大部分互联网公司设置的线上隔离级别是读提交。通过show variables like 'tx_isolation'可以查看数据库事务级别。

有个我觉得很有意思能帮助理解的例子,看这里,对于“脏读”,“不可重复读”,“幻读”的解释,例子里也说的很清楚~

MVCC

解决以上“脏读”,“不可重复读”,“幻读”有两种思路,一个就是加锁,另外一个就是MVCC(Multi-version Concurrency Control)即数据多版本并发控制。MVCC的目的:让读写互相不阻塞,提高事务并发处理的能力。MVCC的核心思想:提供数据的历史版本,即我记录的不是一个静态的2D的表,而是一个“3D”的表,每个数据还有一个维度是他的版本号(transaction id/trx_id,该id按照先后严格递增)。

一致性视图

InnoDB在实现MVCC的时候,用到了一致性视图(consistent read view)。这个视图和我们查询的时候的视图不是一个同一个东西。这个一致性视图其实是根据数据的最新版本和undo log(回滚日志)计算出来的。

以可重复读举例,事务一开始的时候,就创建了一个一致性视图,该视图的数据,如上所述是根据数据当时的最新版本和undo log计算出来的。而这个视图计算出的数据满足以下条件:

  1. 数据版本未提交,不可见 --> 还要根据undo log往前翻版本
  2. 数据版本已提交,但是是在视图创建后提交的,不可见
  3. 数据版本已提交,视图创建前提交的,可见

总的来说,就是根据当前最新数据,和undo log,找到一个提交过的最新版本,作为一致性视图。

一个栗子

上一篇:Java RandomAccessFile从开始截断


下一篇:java基础知识回顾之java Thread类学习(三)--java多线程通信等待唤醒机制(wait和notify,notifyAll)