事务的特性(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
的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读
。简单的说,幻读
指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的幻影
行。InnoDB
和Falcon
存储引擎通过多版本并发控制(MVCC
)机制解决了该问题。
串行化(Serializable ):
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
本文由 feng 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:2021-03-04 00:00:00