事物隔离级别

为了模拟并发环境,SQL SERVER中打开两个查询窗口(分别表示事务1、事务2)即可,并发用户用事务1,事务2简称

测试表脚本:
CREATE TABLE [Customer](
        [CustID] [int] NOT NULL,
        [Fname] [nvarchar](20),
        [Lname] [nvarchar](20),
        [Address] [nvarchar](50),
        [City] [nvarchar](20),
        [State] [nchar](2) DEFAULT (‘CA‘),
        [Zip] [nchar](5) NOT NULL,
        [Phone] [nchar](10)
)
insert into customer values(1, ‘Gary‘, ‘Mckee‘, ‘111 Main‘, ‘Palm Springs‘, ‘CA‘, 94312, 7605551212)
insert into customer values(2, ‘Tom‘, ‘Smith‘, ‘609 Geogia‘, ‘Fresno‘ ‘JP‘, 33045, 5105551212)
insert into customer values(3, ‘Jams‘, ‘bond‘, ‘ST Geogie 21‘, ‘Washington‘, ‘NY‘, 20331, 4405551864)

sqlserver事务隔离级别的测试:
1、read uncommitted:可以读取其他事务未提交的数据
打开事务1,运行:
begin tran
select * from customer
        update customer set state = ‘TN‘ where CustID = 3
转到事务2,运行:
set transaction isolation level read uncommitted
begin tran
select * from customer
此时看到的数据是事务1已经更新但还未提交的(3号记录state值TN)
2、read committed:只能读取其他事务已经提交的数据(有进行修改的)
打开事务1,运行:
begin tran
select * from customer
        update customer set state = ‘TN‘ where CustID = 3
转到事务2,运行:
set transaction isolation level read committed
begin tran
select * from customer
此时会发现事务2一直等待,并不结束
3、repeatable read:保证使用该隔离级别的事务,在读取数据时的数据保持一致,不会被别的事务修改、删除数据(因为别的事务如果有修改、删除操作会被阻塞)
开始事务1,修改事务级别为可重复读,执行:
set transaction isolation level repeatable read
begin tran
select * from customer where State = ‘CA‘
得到1条记录,这个时候事务2中运行:
set transaction isolation level repeatable read
begin tran
update Customer set state = ‘JP‘ where state = ‘CA‘
commit
会发现事务2一直等待,并不结束。返回事务1,运行:
select * from customer where State = ‘CA‘                --2次读取结果一致
commit
事务1成功结束后,再返回事务2,发现事务2也完成了。通过锁机制阻塞其它事务的修改,保持了事务期间读取的一致性
4、serializable:使用该隔离级别的事务用到的表将全部锁定,其他事务不可以进行添加、修改、删除
开始事务1,修改事务级别为序列化级别,执行:
set transaction isolation level serializable
begin tran
select * from customer
开始事务2,执行:
begin tran
update Customer set state = ‘JP‘ where state = ‘CA‘
会发现事务2一直等待
5、snapshot:快照隔离
注意:要向使用快照隔离必须先设置当前数据库能进行快照隔离
如:
ALTER DATABASE NetBarDB
SET ALLOW_SNAPSHOT_ISOLATION ON
在SNAPSHOT隔离下运行的事务将读取数据,
然后由另一事务修改此数据。SNAPSHOT事务不阻塞由其他事务执行的更新操作,
它忽略数据的修改继续从版本化的行读取数据。
开始事务1,修改事务级别为快照级别,执行:
set transaction isolation level snapshot
begin tran
select * from customer
开始事务2,执行:
begin tran
update customer set state = ‘TN‘ where CustID = 3
发现有一行被修改
回到事务1,执行
select * from customer
发现查询出来的CustID = 3的state仍然是‘NY‘并不是‘TN‘

sqlserver事务常见的情况:
1、丢失更新
Sqlserver默认隔离级别是提交读(read committed),在该级别下,可能会有丢失更新的问题。
SQL SERVER
打开事务1运行:
set transaction isolation level read committed
begin tran
select * from customer                --看到3条记录
现在切换到事务2,此时事务1还未结束。在事务2中运行:
set transaction isolation level read committed
begin tran
select * from customer                --看到3条记录,和事务1中相同
现在假设事务1事务继续运行,修改数据并提交:
update customer set state = ‘TK‘ where CustID = 3
commit
回到事务2,事务2根据先前查询到的结果修改数据:
update customer set Zip = 99999 where state = ‘NY‘
commit
结果因为事务1已经修改了事务2的where条件数据,事务2未成功修改数据(其实准确的说应该算是幻象读引起的更新失败。不过若满足条件的记录数多的话,事务2的update可能更新比预期的数量少的记录数,也可算“丢失”了部分本应完成的更新。个人认为只要明白实际上发生了什么即可,不必过分追究字眼)。丢失更新还可能有别的情形,比如事务2也是
update customer set state = ‘KO‘ where CustID = 3
两个事务都结束后,事务2的结果反映到数据库中,但事务1的更新丢失了,事务2也不知道自己覆盖了事务1的更新。

2、脏读演示
sqlserver的默认隔离级别是提交读(read committed)
打开事务1,运行:
begin tran
select * from customer
        update customer set state = ‘TN‘ where CustID = 3
转到事务2,运行:
set transaction isolation level read uncommitted
begin tran
select * from customer
此时看到的数据是事务1已经更新但还未提交的(3号记录state值TN)。而如果事务1发觉数据处理有误,转到事务1,进行回滚:
        Rollback
此时事务2如根据刚读取的数据进一步处理,会造成错误。它读取的数据并未更新到数据库,是“脏”的

3、不可重复读
Sql server的默认级别没有脏读问题,但存在不可重复读问题。
打开事务1,运行:
set transaction isolation level read committed
begin tran
select * from customer where State = ‘CA‘
可以得到1条记录,这个时候事务2中运行:
set transaction isolation level read committed
begin tran
update Customer set state = ‘JP‘ where state = ‘CA‘
commit
事务2插入一条记录并提交。回到事务1,事务1继续运行,此时它再次相同的查询,并借此作进一步修改,却发现读取到的数据发生了变化。
select * from customer where State = ‘CA‘
--2次读取不一致,之后的数据处理应该取消。否则不正确
update Customer set city = ‘garden‘ where state = ‘CA‘
commit
读取未能获得记录。也就是说在同一事务中两次相同的查询获得了不同的结果,产生读取不可重复现象

4、幻像读
当sqlserver的隔离级别设置为可重复读(repeatable read),可以解决上面例子出现的问题。其内部是通过事务期间保持读锁来实现的。
开始事务1,修改事务级别为可重复读,执行:
set transaction isolation level repeatable read
begin tran
select * from customer where State = ‘CA‘
和上例一样得到1条记录,这个时候事务2中运行:
set transaction isolation level repeatable read
begin tran
update Customer set state = ‘JP‘ where state = ‘CA‘
commit
会发现事务2一直等待,并不结束。返回事务1,运行:
select * from customer where State = ‘CA‘                --2次读取结果一致
update Customer set city = ‘garden‘ where state = ‘CA‘
commit
事务2成功结束后,再返回事务1,发现事务1也完成了。通过锁机制阻塞其它事务的修改,保持了事务期间读取的一致性。然而,如果是插入数据,则还是会出现问题:
开始事务1,修改事务级别为可重复读,执行:
set transaction isolation level repeatable read
begin tran
select * from customer where State = ‘CA‘
得到1条记录,这个时候事务2中运行:
set transaction isolation level repeatable read
begin tran
insert into customer values(4, ‘hellow‘, ‘world‘, ‘paradise 001‘, ‘garden‘, ‘CA‘, 00000, 1119995555)
commit
发现事务2立刻提交并正常结束了。返回事务1,运行:
select * from customer where State = ‘CA‘
会发现得到了2条记录。这种现象就叫做幻像读。

时间: 2024-12-28 17:22:38

事物隔离级别的相关文章

事物及事物隔离级别

什么是事物 事物是访问数据库的一个操作序列,数据库应用系统通过事物集来完成对数据库的存取.事物的正确执行使得数据库从一种状态转换为另一种状态. 事物必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性(isolation).持久性(durability)的缩写,这四种状态的意思是: 1.原子性 即不可分割,事物要么全部被执行,要么全部不执行.如果事物的所有子事物全部提交成功,则所有的数据库操作被提交,数据库状态发生变化:如果

Oracle 事物隔离级别

1.事务介绍 Oracle11g中的事务是隐式自动开始的,不需要用户显示的执行开始事务语句.但对于事务的结束处理,则需要用户进行指定的操作.通常在以下情况下,Oracle认为一个事务结束了. (1)  执行Commit语句提交事务 (2)  执行Rollback语句撤销事务 (3)  执行一条数据定义语句.如果该语句执行成功,那么oracle系统会自动执行commit命令:否则,系统会自动执行Rollback命令. (4)  执行一个数据控制命令,当语句执行完毕,oracle系统会自动执行com

数据库的事物隔离级别以及锁的一些个人理解

数据库的 基本分为 共享锁和排它锁 排它锁顾名思义,不能和其他任何所共存. 以SqlServer中某一行数据为例, 特殊的,WithNoLock 这个是不给数据加上任何锁,所以根本和锁没关系 再说update,update的过程是给这条数据加上排它锁,所以当另外事物过来要求修改这条数据的时候,会由于排它锁的互斥,导致无法申请到排它锁,从而实现同一时间只有一个事物对同一条数据进行修改.同样当该条数据正在修改中但其所属的事物还未提交的时候,查询需要在这条数据上加上共享锁的过程也由于排它锁的存在导致被

事物隔离级别_悲观与乐观锁

  1.我印象中的事物事务是一种机制,它确保多个SQL语句被当作完整的操作单元来处理,所有的操作都完成时统一提交. 2.关系数据库的事务特性(ACID) ACID:原子性: 事务是数据库的逻辑工作单位,而且必须是原子工作单位,对于修改,要么全部执行,要么全部不执行        一致性:事务在完成时,必须是所有的数据都保持一致状态. 隔离型: 一个事务的执行不能被其他事务所影响.事务必须是互相隔离的,防止并发读写同一个数据的情况发生 持久性: 一个事务一旦提交,事物的操作便永久性的保存在DB中.

Hibernate 事物隔离级别 深入探究

目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hibernate事务与并发问题处理(乐观锁与悲观锁) 一.数据库事务的定义 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作.事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源.通过将一组相关操作组合为一个要么全部成功

数据库事物隔离级别通俗理解

转自:http://www.oschina.net/question/258230_134502 总的说,数据库事物无非就两种:读取事物(select).修改事物(update,insert).在没有事物隔离控制的时候,多个事物在同一时刻对同一(数据的操作可能就会影响到最终期望的结果,通常有四种情况 (1) 两个更新事物同时修改一条数据时,很显然这种情况是最严重的了,程序中无论如何也不能出现这种情况,因为它会造成更新的丢失!通俗的讲,我更新时,你丫也更新这不就出问题了吗,艹,不行! (2) 一个

由事物隔离级别引发的血案

今天公司的系统发现一个bug:主表记录的已还款总额和还款记录表里面的偿还金额之和不一致.看到这个问题,我的第一反应是怀疑还款的时候离线锁没生效,导致并发修改主表记录.可是经过查看日志和代码,排除了这个可能性.然后又怀疑可能是由于还款之后,修改已还款总额和还款状态时只调用了jpa的save,没有flush,导致没及时写入数据库,别的线程更新的时候不是最新数据.但再一想,发现不对,因为还款的操作是在事务之中进行的,事务结束,jpa会自动把修改写入数据库,应该不会出现这个问题.后来请来大牛帮忙分析,终

Mysql 查看及设置事物隔离级别

1.查看 SELECT @@tx_isolation 2.设置 2.1所有级别 1)read uncommitted : 读取尚未提交的数据 :哪个问题都不能解决 2)read committed:读取已经提交的数据 :可以解决脏读 ---- oracle默认的 3)repeatable read:重读读取:可以解决脏读 和 不可重复读 ---mysql默认的 4)serializable:串行化:可以解决 脏读 不可重复读 和 虚读---相当于锁表 2.2 设置 设置mysql的隔离级别:se

高性能mysql的事物隔离级别

数据库事务的隔离级别有4种,由低到高分别为Read uncommitted .Read committed .Repeatable read .Serializable .而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读.下面通过事例一一阐述它们的概念与联系. Read uncommitted 读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据. 事例:老板要给程序员发工资,程序员的工资是3.6万/月.但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户