事务的隔离性
Inside君发现一些用户对MySQL InnoDB的锁机制完全不能接受,因为他们大多习惯于Oracle抑或是Microsoft SQL Server等数据库的Read Committed(简称RC)事务隔离级别。但正如Jim Gray在其旷世著作《Transaction Processing: Concepts and Techniques》一书中指出的那样,大部分的数据库其实并不符合真正隔离性(true isolation)的要求。本文将结合理论和工程,来讨论事务隔离性的要求。
面试时通常会问面试者事务ACID属性分别代表什么,甚至这已经成为网易数据库面试的标准题之一。据个人的观察,大多用户对于A、C、D属性的描述都没有太大的问题,但是Isolation这点,往往并不准确。这是因为用户通常认为数据库支持事务,那么它就应该符合ACID特性,也就符合隔离性的要求。
但让我们看看事务处理之父Jim Gray对事务隔离性的定义:
Isolation: Concurrently executing transactions see the stored information as if they were running serially (one after another).
并发执行的事务能够看到存储的信息,好似事务之间是串行执行的。这里看似还是太理论,但是只要解决三个并发问题,事务间就不会有环(cycle),因此就能达到真正隔离性的要求。而这三个问题Jim Gray将其总结为Lost Update、Read Uncommitted、Unrepeatable Read:
最终表P的数据只有3一条记录,数据库日志中记录的内容是:
INSERT INTO P SELECT 3;
DELETE FROM P WHERE a <= 6;
那么如果将上述日志传送到从机(slave)去执行,会发现从机中表P的记录数为0,也就是主从数据不一致了。而总结来看,是不是发生了并发执行的事务与串行执行的事务结果是不一样的,那么也就是说,这是不符合事务隔离性的要求。
那么在MySQL数据库中是如何解决这个问题的呢?如果事务的隔离级别是RC,必须将日志格式设置为ROW。这样的日志格式在Inside君看来,更接近于状态机机制,从而也就解决了不一致的问题。Oracle、Microsoft SQL Server数据库都是基于页的物理逻辑复制,所以也不存在这样的问题。但是从严格理论范畴的角度看,RC不符合事务真正隔离型的要求。
事务的隔离级别
数据库厂商们肯定知道隔离性的真正要求,然而他们在某种程度上做了妥协,从而产生了四个不同的隔离程度(isolation degree),Degree 0、Degree 1、Degree 2、Degree 3,分别允许Lost Update、Read Uncommitted、Unrepeatable Read的问题存在,而Degree 3才是真正符合隔离性的要求。
而ANS SQL标准没有从隔离程度进行定义,而是定义了事务的隔离级别,同时定义了不同事务隔离级别解决的三大并发问题: