隔离性与隔离级别
- ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、持久性、隔离性)
SQL 规范的事务隔离级别包含:
- 读未提交(read uncommitted)
- 读提交(read committed)
- 可反复读(repeatable read)
- 串行化(serializable)
在实现上,数据库外面会创立一个视图,拜访的时候以视图的逻辑后果为准。
- “读未提交”隔离级别下间接返回记录上的最新值,没有视图概念;
- 在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创立的
- 在“可反复读”隔离级别下,这个视图是在事务启动时创立的,整个事务存在期间都用这个视图
- “串行化”隔离级别下间接用加锁的形式来防止并行拜访
oracle 默认是读提交、mysql 默认是可反复读
mvcc
- InnoDB 外面每个事务有一个惟一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务零碎申请的,是按申请程序严格递增的
-
而每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。同时,旧的数据版本要保留,并且在新的数据版本中,可能有信息能够间接拿到它
- 也就是说,数据表中的一行记录,其实可能有多个版本 (row),每个版本有本人的 row trx_id
- 每一行的多个版本 v1,v2,v3 并不是实在存在的,而是以后版本通过 undolog 算进去的
-
依照可反复读的定义,一个事务启动的时候,可能看到所有曾经提交的事务后果。然而之后,这个事务执行期间,其余事务的更新对它不可见
- 在实现上,InnoDB 为每个事务结构了一个数组,用来保留这个事务启动霎时,以后正在“沉闷”的所有事务 ID。“沉闷”指的就是,启动了但还没提交
- 数组外面事务 ID 的最小值记为低水位,以后零碎外面曾经创立过的事务 ID 的最大值加 1 记为高水位, 这个视图数组和高水位,就组成了以后事务的一致性视图(read-view)
-
对于以后事务的启动霎时来说,一个数据版本的 row trx_id,有以下几种可能
- 如果一个数据的版本 row trx_id< 低水位示意这个版本是已提交的事务或者是以后事务本人生成的,这个数据是可见的
- 如果一个数据的版本 row trx_id > 高水位示意是未来的事务生成的,必定不可见
-
如果一个数据的版本 row trx_id 在低水位与高水位之间,有两种可能
- 若在数组中,是未提交的批改,不可见
-
不在数组中,是提交的批改,可见
- 假如数组是 [1,2,3,5],查看的数据版本是 4,这意味着在事务启动时,[1,2,3,5] 事务都没有提交,然而 4 提交了,所以 4 是能够被看到的。这也阐明低水位~高水位数字范畴之间的 row trx_id 并不是都没有提交的,而是不在数组中的就是曾经被提交的
- 本人的事务版本可见
-
更新数据都是先读后写的,而这个读,只能读以后的值,称为“以后读”(current read)
-
除了 update 语句外,select 语句如果加锁,也是以后读
- select k from t where id=1 lock in share mode; 读锁
- select k from t where id=1 for update; 写锁
- 假如事务 a 对于某一行的以后读(更新或 select 加锁),事务 b 正在更新,然而还没提交,此时事务 a 的以后读会被阻塞
-