首页 > 数据库技术 > 详细

数据库事务的隔离级别

时间:2019-04-17 20:14:01      阅读:104      评论:0      收藏:0      [点我收藏+]

数据库事务的隔离级别

什么是事务的隔离性?

任何支持事务的数据库,都必须具备四个特性,分别是:

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

也就是我们常说的事务ACID,这样才能保证事务中数据的正确性。而事务的隔离性就是指,多个并发的事务同时访问一个数据库时,一个事务不应该被另一个事务所干扰,每个并发的事务间要相互进行隔离。

没有事务隔离会出现什么现象?

脏读 Dirty Read

一个事务读到另一个事务还没有提交的记录

-- 事务A
START TRANSACTION ;
insert into user(id, name) values(100, '张三');
-- COMMIT; 事务A 未提交
-- 此时事务B
select * from user where id = 100; //这里可以查询出 ‘张三’ 这条记录。
-- 如果事务A进行ROLLBACK,事务B就会发现查出了不存在的数据。这种现象就是脏读。

不可重复读 Unrepeatable Read

一个事务在自己没有更新数据库数据的情况,同一个查询操作执行两次或多次的结果应该是一致的;如果不一致,就说明为不可重复读。

-- 事务A
START TRANSACTION ;
select * from user where id = 100; //这里查询出 ‘张三’
-- 此时事务B 修改记录并提交
update user set name = '李四' where id = 100;
-- 事务A再次查询
select * from user where id = 100; //这里查询出 ‘李四’
-- 事务A在同一事务里查询两次结果不一致,这种现象叫不可重复读。

幻读 Phantom Problem (虚读)

事务A读的时候读出了15条记录,事务B在事务A执行的过程中 增加 了1条,事务A再读的时候就变成了 16 条,这种情况就叫做幻影读。

-- 事务A
START TRANSACTION ;
select * from user where id  < 200; //这里查询出10条记录
-- 此时事务B 新增用户 或 删除用户
insert into user(id, name) values(101, '牛二');
-- 事务A再次查询
select * from user where id  < 200; //这里查询出11条记录
-- 事务A在同一事务里查询两次结果集记录数不一致,这种现象叫幻读。

为了防止出现脏读、不可重复读、幻读等情况,我们就需要根据我们的实际需求来设置数据库的隔离级别

READ_UNCOMMITTED 读未提交

在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。

如无特殊情况,基本是不会使用这种隔离级别的

READ_COMMITED 读已提交

这是系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读。当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞,这种情况下,并发能力就相当的差,但数据库有快照(snapshot)的概念。快照既能保证数据一致性又不加锁。当一个更新的事务没有提交时,另一个对更新数据会从快照数据进行查询,这样既能保证并发能力又能保证数据一致性。读提交只能避免脏读,并不能避免不可重复读和幻读。

除非在查询中显示的加锁,不然,普通的查询是不会加锁的。加锁语句:

select * from user where id=100 lock in share mode;
select * from user where id=100 for update;

REPEATABLE_READ 可重复读

它也是MySql的默认隔离级别,在这个级别下,普通的查询同样是使用的快照读,但是,和读提交不同的是,当事务启动时,就不允许进行修改操作(Update)了,而不可重复读恰恰是因为两次读取之间进行了数据的修改,因此,REPEATABLE_READ能够有效的避免不可重复读,但却避免不了幻读,因为幻读是由于插入或者删除操作(Insert or Delete)而产生的。

此处有例外,因为INNODB采用了Gap锁,所以RR级别可以避免幻读,想了解什么是Gap锁,请移步另一篇文章。// TODO 博客链接

SERLALIZABLE 序列化

这是数据库最高的隔离级别,这种级别下,事务串行化顺序执行,也就是一个一个排队执行,这种级别下,脏读、不可重复读、幻读都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用


事务隔离级别 脏读 不可重复读 幻读
未提交读RU 可能 可能 可能
已提交读RC 不可能 可能 可能
可重复读RR 不可能 不可能 可能(INNODB不可能)
串行化S 不可能 不可能 不可能

查看MySQL当前隔离级别

select @@tx_isolation

修改MySQL全局隔离级别

set global transaction isolation level repeatable read;
select @@global.tx_isolation;

数据库事务的隔离级别

原文:https://www.cnblogs.com/PlacidZhang/p/10725641.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!