数据库的隔离级别

博客分类: software 阅读次数: comments

数据库的隔离级别

事务的特性(ACID):

原子性( Atomicity )一致性( Consistency )隔离性( Isolation ) 持续性( Durability )

事务的隔离性(Isolation)

隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离。

如果不考虑隔离性,会发生什么事呢

脏读

脏读是指一个事务在处理数据的过程中,读取到另一个为提交事务的数据。

id name
1 feng
START TRANSACTION;
UPDATA `table` SET `name `= 'canren' WHERE `id` = 1;    --此时事务2查询id = 1
ROLLBACK;
 
SELECT * FROM `table` WHERE `id` = 1;        --查询到 id = 1, name = 'canren'

事务1 并没有提交,name 还是 lisi,但是事务2却读到了 name = canren ,这就是 脏读

不可重复读

不可重复读是指对于数据库中的某个数据,一个事务范围内的多次查询却返回了不同的结果,这是由于在查询过程中,数据被另外一个事务修改并提交了。

id name
1 feng
START TRANSACTION;
SELECT * FROM `table` WHERE `id` = 1;    -- 查询到 id = 1, name = feng

START TRANSACTION;
UPDATE `table` SET `name` = 'canren' WHERE `id` = 1;
COMMIT;

SELECT * FROM `table` WHERE `id` = 1;    -- 查询到 id = 1, name = canren
COMMIT;

不可重复读脏读 的区别是,脏读 读取到的是一个 未提交的数据,而 不可重复读 读取到的是 前一个事务 提交的数据。

不可重复读 在一些情况也并不影响数据的正确性,比如需要多次查询的数据也是要以最后一次查询到的数据为主。

幻读

幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

id name
1 feng
START TRANSACTION;
SELECT * FROM `table` WHERE `id` = 2;    --返回 NULL,此时事务2提交

START TRANSACTION;
INSERT INTO `table` VALUES(2, 'canren');
COMMIT;

SELECT * FROM `table` WHERE `id` = 2;    --返回 id = 2, name = canren
COMMIT;

不可重复读幻读 是初学者不易分清的概念,我也是看了详细的解读才明白的,总的来说,解决 不可重复读 的方法是 锁行,解决 幻读 的方式是 锁表

四种隔离级别解决了上述问题

读未提交(Read uncommitted):

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

读已提交(Read committed):

这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也不支持所谓的 不可重复读 ,因为同一事务的其他实例在该实例处理其间可能会有新的 commit ,所以同一 select 可能返回不同结果。

可重复读(Repeatable read):

这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 。简单的说,幻读 指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的 幻影 行。InnoDBFalcon 存储引擎通过多版本并发控制( MVCC)机制解决了该问题。

串行化(Serializable ):

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。