SqlServer 并发事务(一):事务隔离级别

--查了当前数据库是事务隔离级别
DBCC USEROPTIONS

表初始内容:

SELECT * FROM Test  Wherename=‘kk‘

id  name   info

1   kk      NULL

【测试一:丢失更新】

--事务1
begin tran
	select * from dbo.Test(nolock) where name = 'kk'
	waitfor delay '00:00:05'
	update T set info = 'A更改' from Test T(nolock) where name = 'kk'
commit tran

--事务2
begin tran
	select * from dbo.Test(nolock) where name = 'kk'
	waitfor delay '00:00:05'
	update T set info = 'B更改' from Test T(nolock) where name = 'kk'
commit tran

事务1和事务2的运行结果:

id  name   info

1   kk      NULL

事务结束最后结果:

SELECT *
FROM Test  Wherename=‘kk‘

id  name   info

1   kk      B更改

说明:【事务1】更改了数据,但是没有被读到。最终【事务2】的更改覆盖了【事务1】的更改值

解决:允许对事务操作加锁,即取消(nolock),nolock级别最低。

当前使用:SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTED

(READ UNCOMMITTED:即未提交的数据只能读取,不能更改)

【测试二:脏读】

--事务1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
begin tran
	update T set info = 'A更改' from Test T where name = 'kk'
	waitfor delay '00:00:05'
rollback tran --回滚

--事务2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
begin tran
	select * from dbo.Test where name = 'kk'
commit tran

事务2的运行结果:

id  name   info

1   kk      A更改

事务结束最后结果:

SELECT *
FROM Test  Wherename=‘kk‘

id  name   info

1   kk      NULL

说明:【事务1】更改了数据,【事务2】读取了表中更改的值,【事务1】回滚。最终的表是没有被更改的。

解决一:提高隔离级别

SET TRANSACTIONISOLATIONLEVELREADCOMMITTED

ALTER DATABASEDBNameSETREAD_COMMITTED_SNAPSHOTOFF(默认OFF)

此时【事务1】等待事务【事务2】完成后才读取表中的值。

(READ COMMITTED:更改的数据只能是提交后才能读取)

解决二:

SET TRANSACTIONISOLATIONLEVELREADCOMMITTED

ALTER DATABASEDBNameSETREAD_COMMITTED_SNAPSHOTON(默认OFF)

此时【事务2】读到的是表中之前的快照值(不必等待【事务1】完成)。

此时相当于:

SET TRANSACTIONISOLATIONLEVELREADCOMMITTED

select *
from dbo.TestWITH(READPAST)wherename=‘kk‘

解决三:

事务2用表提示READCOMMITTEDLOCK把语句级别改为READCOMMITTED

--事务2

SET TRANSACTIONISOLATIONLEVELREADUNCOMMITTED

begin tran

select
*from dbo.TestWITH(READCOMMITTEDLOCK)wherename=‘kk‘

commit tran

如果将 READ_COMMITTED_SNAPSHOT设置为OFF(默认设置),设置时关闭所有对此数据库的连接,

数据库引擎会使用共享锁防止其他事务在当前事务执行读取操作期间修改行。

共享锁还会阻止语句在其他事务完成之前读取由这些事务修改的行。

【测试三:不可重读】

--事务1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
begin tran
	select * from dbo.Test where name = 'kk'
	waitfor delay '00:00:05'
	select * from dbo.Test where name = 'kk'
commit tran 

--事务2
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
begin tran
	update T set info = 'B更改' from Test T where name = 'kk'
commit tran

事务2的运行结果:

id  name   info

1   kk      NULL

id  name   info

1   kk      B更改

事务结束最后结果:

SELECT *
FROM Test  Wherename=‘kk‘

id  name   info

1   kk      B更改

说明:【事务1】读取了数据,【事务2】更改数据,【事务1】再读取数据。【事务1】两次读取都不一样!

解决一:提高隔离级别

SET TRANSACTIONISOLATIONLEVELREPEATABLEREAD

(REPEATABLE READ:允许重复读取数据,但读取的都是第一次读取的副本)

解决二:更改为快照级别

ALTER DATABASEDBNameSETALLOW_SNAPSHOT_ISOLATIONON

SET TRANSACTIONISOLATIONLEVELSNAPSHOT

此时【事务1】的运行结果2次都一样,读到的都是未更改前的值:

id  name   info

1   kk      NULL

【测试四:幻读】

--事务1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin tran
	select * from dbo.Test where name = 'kk'
	waitfor delay '00:00:05'
	select * from dbo.Test where name = 'kk'
commit tran

--事务2
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin tran
	INSERT INTO Test VALUES(2,'kk',null)
commit tran

事务2的运行结果:

id  name   info

1   kk      NULL

id  name   info

1   kk      NULL

2   kk      NULL

事务结束最后结果:

SELECT *
FROM Test  Wherename=‘kk‘

id  name   info

1   kk      NULL

2   kk      NULL

说明:【事务1】读取了数据,【事务2】插入了数据,【事务1】再读取数据。【事务1】两次读取都不一样!幻觉?

解决:提高隔离级别

SET TRANSACTIONISOLATIONLEVELSERIALIZABLE

此时【事务2】等待【事务1】完成。

事务1的运行结果2次都一样:

id  name   info

1   kk      NULL

范围锁:范围锁处于与事务中执行的每个语句的搜索条件相匹配的键值范围之内。这样可以阻止其他事务更新或插入任何行,从而限定当前事务所执行的任何语句。这意味着如果再次执行事务中的任何语句,则这些语句便会读取同一组行。在事务完成之前将一直保持范围锁。这是限制最多的隔离级别,因为它锁定了键的整个范围,并在事务完成之前一直保持范围锁。因为并发级别较低,所以应只在必要时才使用该选项。该选项的作用与在事务内所有SELECT语句中的所有表上设置HOLDLOCK相同。

如果在批处理中设置
REPEATABLE READ,并且该批处理调用一个将隔离级别设置为SERIALIZABLE的存储过程,则当该存储过程将控制返回给该批处理时,隔离级别就会恢复为REPEATABLEREAD。


并发事务引起的问题


      问题          


                    描述                      


              结果             


                          解决                     


丢失更新


A读—B读—A改—B改


A更改丢失


READ UNCOMMITTED


脏读


A改—B读—A回滚


B读无效值


READ COMMITTED


不可重读


A读—B改—A读


A读不一致


REPEATABLE READ


不可重读


A读—B改—A读


A读不一致


SNAPSHOT


幻读


A读—B增删—A读


A读或多或少


SERIALIZABLE

参考:SET TRANSACTION ISOLATION LEVEL (Transact-SQL)

时间: 2024-11-03 03:06:32

SqlServer 并发事务(一):事务隔离级别的相关文章

数据库事务中的隔离级别和锁+spring Transactional注解

数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题. ACID 首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(Atomicity):即事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做,不能只做一部分:一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是处于正确的状态,即数据完整性约束没有被破坏:比如我们做银行转账的相关业务,A转账给B,要求

MySQL事务四个隔离级别

MySQL事务隔离级别详解             MySQL数据结构SQL SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. Read Uncommitted (读取未提交的内容)  在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取未提交的数据,也被称之为脏读(Dirty Read).Read Commit

数据库事务的四大特性以及事务的隔离级别-与-Spring事务传播机制&隔离级别

本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响. ⑵ 一致性(Consistency) 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执

SqlServer——事务—锁与隔离级别

隔离实际上是通过锁来实现的,作用于整个事务,它通常在事务开始前指定,如 SET TRANSACTION ISOLATION LEVEL READ Committed,指定后面的事务为 已提交读:而锁是在我们执行某一具体的SQL语句时在from中指定锁模式来实现的,它可以覆盖掉已指定隔离级别下应用的锁类型.隔离级别牺牲并发性来实现一致性. 并发:是指在相同的时间,多个用户访问相同的数据.它通常引起以下问题:脏读:丢失更新:不可重复度:幻读: 脏读:一个进程读取了另一个进程尚未提交的数据. 不可重复

事务并发之隔离级别

事务 事务是作为单个逻辑工作单元执行的一系列操作.一个逻辑工作单元必须有四个属性,称为原子性.一致性.隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务. 事务并发 数据库是多个用户(事务)共享的,当多个用户同时访问数据时,那么在这种情况下就叫做并发. 事务并发下可能出现的问题 更新丢失 两个事务都同时更新一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了.这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来. 脏读 一个事务读取到了另一个事务未提交的数据操作结果.

C# 事务的ACID隔离级别

事务的ACID属性如下: 原子性(Atomicity):事务的所有操作是原子工作单元:对于其数据修改,要么全都执行,要么全都不执行.原子性消除了系统处理操作子集的可能性. 一致性(Consistency):数据从一种正确状态转换到另一种正确状态.事务在完成时,必须使所有的数据都保持一致.在相关数据库中,所有规则都必 须应用于事务的修改,以保持所有数据的完整性.当事务结束时,所有的内部数据结构都必须是正确的.在存款取款的例子中,逻辑规则是,钱是不能凭空产生或销 毁的,对于每个(收支)条目必须有一个

数据库事务特性和隔离级别

事务 一组业务操作,要么全部成功,要么全部不成功. ----------------事务的特性-------------- 原子性:一个事务是一个整体,不可分割,事务中的操作要么都成功,要么都失败. 一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态.事务执行前后,数据库的状态是一致的. 例如:A有1000,元,B有1000元,加起来是2000,中间执行转账的操作,转账后两个人的钱加起来还是2000. 隔离性:两个或多个事务并发操作,之间会互相影响.数据库提供了隔离级别来消除这些影响

数据库 之 事务控制和隔离级别

1  概述 事务是指一组原子性的SQL查询.或者是一个或多个SQL语句组成的独立工作单元:MyISAM不流行的原因很大是因为其不支持事务的处理功能. 2  事务日志 事务日志定义属性,有些参数可以运行时修改,写入在配置段里,事务日志相当于是中间的辅助功能,而且很关键. 事务日志表示把操作过程一笔一笔记录下来.如某个线程要对某个行操作,数据库会先保留老版本于事务日志中,对文件的写入,新版本的内容是先写入到日志里,提交前,数据在日志文件中,而不是在数据文件中,提交操作执行后,才将新旧版本的日志清除.

事务管理、隔离级别,日志管理

事务Transactions:一组原子性的SQL语句,或一个独立工作单元事务日志:记录事务信息,实现undo,redo等故障恢复功能ACID特性:A:atomicity原子性:整个事务中的所有操作要么全部成功执行,要么全部失败后回滚C:consistency一致性:数据库总是从一个一致性状态转换为另一个一致性状态I:Isolation隔离性:一个事务所做出的操作在提交之前,是不能为其它事务所见:隔离有多种隔离级别,实现并发D:durability持久性:一旦事务提交,其所做的修改会永久保存于数据

事务与Mysql隔离级别

事务 定义: 比如ABCD四个业务,作为一个事务,他们要么一起都执行完毕,要么都不执行.(只要有一个不成功,那么所有的都不可以成功) 四个特性 ACID 原子性(Atomicity) 整个事务中的所有操作,要么全都完成,要么全部不完成. 事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态. 一致性(Consistency) 事务必须保持系统处于一致的状态,不管在任何时间并发事务有多少. 比如转账,ABCDE五个人每个人初始状态 有 100元,总额是500元. 互相转账的操作