sqlsql server 事务务中出现错误事务会自动中断吗

3561人阅读
Sqlserver/MySql/NoSql(18)
昨日“拜读”《sqlserver2005高级程序设计》和《SQL
Server 2008编程入门经典(第3版)》这两本翻译后的中文版书籍。竟然发现目录结构大致一样,其讲解的内容几乎差不多。有抄袭的嫌疑。看到“事务和锁”那一张中,发现连举的小例子、表格都一模一样。哈哈。。。对这类书籍,真不想做太多评论了。国内那些翻译版的书籍嘛。说真的,大部分翻译得有点生硬。而那些“原创著作”嘛。大多是相互抄袭,空谈。就微软技术体系而言,如果直接从MSDN或者联机丛书中copy一下,再随便贴几页的代码,那样就能出版销售,那可能我也能著书了,因为那确实没啥水平。
当然,也不乏精品之作,只是很少且很难找到罢了。好了,言归正传,开始说说事务和
锁,这大概是数据库中比较难理解的东西了。
一、脏读、不可重复读、幻读
(1)脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
    张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
    与此同时,
    事务B正在读取张三的工资,读取到张三的工资为8000。
    随后,
    事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
    最后,
    事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
(2)不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
    在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
    与此同时,
    事务B把张三的工资改为8000,并提交了事务。
    随后,
    在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
(3)幻读:&是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
    目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。
    此时,
    事务B插入一条工资也为5000的记录。
    这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。
不可重复读的重点是修改:&
同样的条件,你读取过的数据,再次读取出来发现值不一样了&
幻读的重点在于新增或者删除:
同样的条件,第 1 次和第 2 次读出来的记录数不一样
二、独占锁、共享锁、更新锁,乐观锁、悲观锁
1、锁的两种分类方式
(1)从数据库系统的角度来看,锁分为以下三种类型:
独占锁(Exclusive
  独占锁锁定的资源只允许进行锁定操作的程序使用,其它任何对它的操作均不会被接受。执行数据更新命令,即INSERT、
UPDATE 或DELETE 命令时,SQL Server 会自动使用独占锁。但当对象上有其它锁存在时,无法对其加独占锁。独占锁一直到事务结束才能被释放。
共享锁(Shared
  共享锁锁定的资源可以被其它用户读取,但其它用户不能修改它。在SELECT
命令执行时,SQL Server 通常会对对象进行共享锁锁定。通常加共享锁的数据页被读取完毕后,共享锁就会立即被释放。
更新锁(Update
  更新锁是为了防止死锁而设立的。当SQL
Server 准备更新数据时,它首先对数据对象作更新锁锁定,这样数据将不能被修改,但可以读取。等到SQL Server 确定要进行更新数据操作时,它会自动将更新锁换为独占锁。但当对象上有其它锁存在时,无法对其作更新锁锁定。&&
(2)从程序员的角度看,锁分为以下两种类型:
悲观锁(Pessimistic
  悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。&
乐观锁(Optimistic
  相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。
  而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(
Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
2、数据库中如何使用锁
  首先从悲观锁开始说。在SqlServer等其余很多数据库中,数据的锁定通常采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插入机制,在任何时间同一张表只会插1条数据,别的想插入的数据要等到这一条数据插完以后才能依次插入。带来的后果就是性能的降低,在多用户并发访问的时候,当对一张表进行频繁操作时,会发现响应效率很低,数据库经常处于一种假死状态。而Oracle用的是行级锁,只是对想锁定的数据才进行锁定,其余的数据不相干,所以在对Oracle表中并发插数据的时候,基本上不会有任何影响。
  注:对于悲观锁是针对并发的可能性比较大,而一般在我们的应用中用乐观锁足以。
  Oracle的悲观锁需要利用一条现有的连接,分成两种方式,从SQL语句的区别来看,就是一种是for
update,一种是for update nowait的形式。比如我们看一个例子。
  首先建立测试用的数据库表:
&  CREATE
TABLE TEST(ID,NAME,LOCATION,VALUE,CONSTRAINT test_pk PRIMARY KEY(ID))AS SELECT deptno, dname, loc, 1 FROM scott.dept
  这里我们利用了Oracle的Sample的scott用户的表,把数据copy到我们的test表中。
update 形式介绍
  然后我们看一下for
update锁定方式。我们执行如下的select for update语句:
&  select
* from test where id = 10&for update
&  通过这条检索语句锁定以后,再开另外一个sql*plus窗口进行操作,再把上面这条sql语句执行一便,你会发现sqlplus好像死在那里了,好像检索不到数据的样子,但是也不返回任何结果,就属于卡在那里的感觉。这个时候是什么原因呢,就是一开始的第一个Session中的select
for update语句把数据锁定住了。由于这里锁定的机制是wait的状态(只要不表示nowait那就是wait),所以第二个Session(也就是卡住的那个sql*plus)中当前这个检索就处于等待状态。当第一个session最后commit或者rollback之后,第二个session中的检索结果就是自动跳出来,并且也把数据锁定住。
  不过如果你第二个session中你的检索语句如下所示:select
* from test where id = 10,也就是没有for update这种锁定数据的语句的话,就不会造成阻塞了。
update nowait 形式介绍
  另外一种情况,就是当数据库数据被锁定的时候,也就是执行刚才for update那条sql以后,我们在另外一个session中执行for
update nowait后又是什么样呢。
  比如如下的sql语句:
  select
* from test where id = 10&for
update nowait
  由于这条语句中是制定采用nowait方式来进行检索,所以当发现数据被别的session锁定中的时候,就会迅速返回ORA-00054错误,内容是资源正忙,
但指定以 NOWAIT 方式获取资源。所以在程序中我们可以采用nowait方式迅速判断当前数据是否被锁定中,如果锁定中的话,就要采取相应的业务措施进行处理。
  那这里另外一个问题,就是当我们锁定住数据的时候,我们对数据进行更新和删除的话会是什么样呢。
  比如同样,我们让第一个Session锁定住id=10的那条数据,我们在第二个session中执行如下语句:
  update test set value=2 where id = 10
  这个时候我们发现update语句就好像select for update语句一样也停住卡在这里,当你第一个session放开锁定以后update才能正常运行。当你update运行后,数据又被你update
语句锁定住了,这个时候只要你update后还没有commit,别的session照样不能对数据进行锁定更新等等。
  总之,Oracle中的悲观锁就是利用Oracle的Connection对数据进行锁定。在Oracle中,用这种行级锁带来的性能损失是很小的,只是要注意程序逻辑,不要给你一不小心搞成死锁了就好。而且由于数据的及时锁定,在数据提交时候就不呼出现冲突,可以省去很多恼人的数据冲突处理。缺点就是你必须要始终有一条数据库连接,就是说在整个锁定到最后放开锁的过程中,你的数据库联接要始终保持住。
  与悲观锁相对的,我们有了乐观锁。乐观锁一开始也说了,就是一开始假设不会造成数据冲突,在最后提交的时候再进行数据冲突检测。
在乐观锁中,我们有3种常用的做法来实现:
第一种就是在数据取得的时候把整个数据都copy到应用中,在进行提交的时候比对当前数据库中的数据和开始的时候更新前取得的数据。
  当发现两个数据一模一样以后,就表示没有冲突可以提交,否则则是并发冲突,需要去用业务逻辑进行解决。
第二种乐观锁的做法就是采用版本戳,这个在Hibernate中得到了使用。
  采用版本戳的话,首先需要在你有乐观锁的数据库table上建立一个新的column,比如为number型,当你数据每更新一次的时候,版本数就会往上增加1。
  比如同样有2个session同样对某条数据进行操作。两者都取到当前的数据的版本号为1,当第一个session进行数据更新后,在提交的时候查看到当前数据的版本还为1,和自己一开始取到的版本相同。就正式提交,然后把版本号增加1,这个时候当前数据的版本为2。当第二个session也更新了数据提交的时候,发现数据库中版本为2,和一开始这个session取到的版本号不一致,就知道别人更新过此条数据,这个时候再进行业务处理,比如整个Transaction都Rollback等等操作。
  在用版本戳的时候,可以在应用程序侧使用版本戳的验证,也可以在数据库侧采用Trigger(触发器)来进行验证。不过数据库的Trigger的性能开销还是比较的大,所以能在应用侧进行验证的话还是推荐不用
第三种做法和第二种做法有点类似,就是也新增一个Table的Column,不过这次这个column是采用timestamp型,存储数据最后更新的时间。
  在Oracle9i以后可以采用新的数据类型,也就是timestamp
with time zone类型来做时间戳。这种Timestamp的数据精度在Oracle的时间类型中是最高的,精确到微秒(还没与到纳秒的级别),一般来说,加上数据库处理时间和人的思考动作时间,微秒级别是非常非常够了,其实只要精确到毫秒甚至秒都应该没有什么问题。
  和刚才的版本戳类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。如果不想把代码写在程序中或者由于别的原因无法把代码写在现有的程序中,也可以把这个时间戳乐观锁逻辑写在Trigger或者存储过程中。
三、事务五种隔离级别
Isolation 属性一共支持五种事务设置,具体介绍如下:
(1)DEFAULT
  使用数据库设置的隔离级别(默认),由DBA
默认的设置来决定隔离级别。
(2)READ_UNCOMMITTED
  这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。
  会出现脏读、不可重复读、幻读 (隔离级别最低,并发性能高)。
(3)READ_COMMITTED
  保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
  可以避免脏读,但会出现不可重复读、幻读问题(锁定正在读取的行)。
(4)REPEATABLE_READ
  可以防止脏读、不可重复读,但会出幻读(锁定所读取的所有行)。
(5)SERIALIZABLE
  这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。
  保证所有的情况不会发生(锁表)。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:794801次
积分:9324
积分:9324
排名:第1508名
原创:141篇
转载:15篇
评论:375条
丁码农,非知名架构师。略懂互联网高性能、高并发、高可用的分布式系统架构设计与实现。 在服务化、分库分表、消息中间件、性能调优、分布式搜索、NoSql等方面有一定的研究和实践经验。
微信扫码,向我提问Posts - 13,
Articles - 0,
Comments - 0
12:45 by 昏晓, ... 阅读,
T-SQL中出现的错误,依据和事务的关系,可以分为两种情况:
有的错误会导致发生错误位置之后的代码不再执行,如果错误位置在事务中,该事务也会自动回滚(即在错误位置之后的rollback语句不会执行,但是事务仍然会回滚);在错误位置之后判断@@Error变量的值也是没有意义的,因为错误位置之后的代码根本不执行了。
有的错误不影响发生错误位置之后的代码执行,如果错误位置在事务中,该事务也不会自动回滚;
至于什么样的错误会导致发生错误位置之后的代码不执行,哪些不会,则还没有弄明白。
关于@@ERROR变量:
@ERROR变量,返回的是上一个T-SQL语句的执行结果,如果上一个 Transact-SQL 语句执行成功,@@ERROR 系统函数将返回 0;如果该语句生成错误,@@ERROR 将返回错误号。每个 Transact-SQL 语句完成时,@@ERROR 的值都会更改。这里的&每个&确实是&每个&,即使是使用 if 判断了@@ERROR的值,在 if 语句后的@@ERROR值已经改变了。
得到上述结果的测试代码如下:
1 create table tbl_ligsh_test_transaction(
id int not null identity( 1, 1 ) primary key,
name varchar( 10 )
8 alter procedure ligsh_test_transaction
begin transaction
insert into tbl_ligsh_test_transaction ( name )
values ( 'name' )
--declare @var int
--set @var = '22'
--raiserror( N'message', 16, 1 )
if @@error = 0
insert into tbl_ligsh_test_transaction( name )
values ( 'name' )
rollback transaction
commit transactionSQL Server中事务和并发详解
作者:佚名
字体:[ ] 来源:互联网 时间:12-09 15:11:06
事物是SQL Server中的基本工作单元。通常它由几个读取和更新数据库的SQL命令组成,但是这些操作都不被看为最终的
A、Transaction(事务)是什么:
事物是SQL Server中的基本工作单元。通常它由几个读取和更新数据库的SQL命令组成,但是这些操作都不被看为最终的,直到发出一个COMMIT命令为止。&事务是作为单一工作单元而执行的一系列操作。包括增删查改。
2、事务的种类:
&事务分为显示事务和隐式事务:
隐式事务:就是平常我们使用每一条sql 语句就是一个事务,只不过他们执行完成之后事务就跟着结束了。
显示事务:就是需要我们来手写了,这个时候就可以进行控制事务的开始和结束了。
1 --显式事务(对事物可以进行控制) 2
3 --开始事务 4 5 update [Sales.Shippers] 6 set companyname='顺丰' where shipperid=5; 7
8 select * from [Sales.Shippers]; 9 10 --结束事务:11 --第一种:事务的回滚1213 14 --第二种:事务的提交15
3、事务很重要的四个属性:&
&1、原子性:事务必须是原子工作单位。&&在事务中修改数据,要么全都执行,要么全都不执行。在事务执行完成之前(调提交指令写入到sql的事务日志之前),出现问题或重启,sql server 会回滚所有的修改事务。 但是也有例外的错误不会回滚事务&&&&例如:主键冲突和锁超时等。 &错误日志会 捕获这些错误的指令,并记录日志里面,然后执行一些操作(例如:回滚事务)
2、一致性:发生在同一进程的事物里面的 修改和 查询是不会产生冲突的。保持访问的数据的一致性。
3、隔离性:控制数据访问的机制; 说明: 一个事务正在对一个表的数据正在修改, 还没有执行完成;;这时另一个事务,想要查询里面的数据,是不能查到的,必须等到 修改的事务执行完成。:sql server 采用的 &锁&的机制,将正在修改的事务 处理的表的数据 锁定。这样是为了保证数据同步,数据的一致性。
4、持久性: &当一个事务的指令 已经提交到 事务日志里面,即使磁盘上的数据还没有修改,这个时候数据库的服务停止,在服务重启的时候还会将事务日志里的指令执行(进行回复处理)。保证数据的持久性。
B、什么是并发性?并发性可以定义为多个进程在相同时间访问或者更改共享数据的能力。既然是能力,那么一个系统的并发性就会有强弱之分。既然如此,我们该怎样判断一个系统并发行的强弱呢?一般情况而言,一个系统在互不干扰的情况下可以激活的并发用户的进程数越多,该系统的并发性就越强。可能影响并发性的一些原因分析:当正在更改数据的进程阻止其他进程读取该数据时,或者当读取数据的进程阻止其他进程更改该数据时,并发行会减弱。另外,当多个进程试图同时更改相同数据时,且无法在不牺牲数据的一致性的前提下都能成功时,并发性也会受到影响。对于并发性的理解我们和容易联想到铁道部的订票网站。由于处理并发性能力不够,导致订票高峰出现奔溃现象,对网络订票造成不良影响。由此可见,一个大型网站的数据库系统提高处理并发性的能力是在必要。
处理并发性的方法:
SQLServer 2008提供两种方法:乐观和悲观两个模型。我们可以通过一下命令来指定:SETTRANSACTION ISOLATION LEVEL(事物的隔离级别)来指定。
两者的区别:在两种模型中,两个进程试图在相同时间修改相同数据时,可能会出现冲突。那么这两个模型之间的区别在于冲突是在出现前被避免还是在出现后采取某种方式进行处理。悲观并发模型:对于悲观并发SQL Server默认的行为是获取锁来阻塞对另一个进程正在使用的数据的访问。悲观并发假设系统中有足够的数据修改操作,因而给定的任何一个读写操作都可能受到另外一个用户的数据修改操作的影响。悲观并发通过获得正在被读取数据上的锁,使其他进程无法修改该数据而避免冲突。换言之,在悲观模型下,读取者阻塞写入者,写入者也阻塞读取者。乐观并发模型:乐观并发假设系统中有足够少的数据修改操作,因而任何单个事物都不太可能另一个事物正在修改的数据。乐观并发的默认行为是使用行版本控制来允许数据读取者看到修改之前的数据状态。数据行教老的版本被保存,所以读取数据的进程可以看到进程开始读取时的数据,不会受到对该数据正在做出任何更改的进程的影响。换言之,读取者不阻塞写入者,写入者也不阻塞读取者,但是,写入者可以而且会阻塞写入者,这也是导致冲突的原因所在。这时SQL Server在冲突出现时产生一个错误信息,但是是由应用程序来负责影响该错误。
上面将基本的事务介绍了一下,下面开始介绍并发。所以必须要介绍就是事务的&锁&。
4、事务中的锁
&事务中都含有什么锁呢?
最常用的锁:排它锁(独占锁)和共享锁,还有其他的锁,这里就不做介绍了,比如:更新锁、架构锁、意向锁等。
5、排它锁和共享锁
当一个事务执行更新修改操作的时候会申请排它锁,主要是在写操作里面使用。需要注意的两点:1、一个事务含有排它锁,就不能含有其他任何锁。2、一条数据只能被一个排它锁锁住,就不能再被其他排他锁锁定。
&主要是在读操作中使用,并且多个事务可以同时对一条数据使用共享锁。
排它锁和共享锁最重要的区别:排它锁是不能被控制他的处理方式和时间,但是共享锁是可以控制其隔离级别来控制其处理的时间。
12 update [Sales.Shippers] set companyname='顺丰' where shipperid=5;3 --事务还没有查询完成,为这条数据 加上一个 排它锁。这时这条数据就不能被其他进程 访问到
事务还没有执行完成,再开一个线程,执行查询操作
1 select * from [Sales.Shippers] where shipperid=5
因为读操作默认使用的共享锁,但是这个时候这条数据已经被其他线程的排它锁锁住,所以会造成阻塞,直到排它锁释放。
6、隔离级别&
&首先要先明白三点:
1、用于控制并发用户如何读写数据的操做。
2、读操作默认使用共享锁;写操作需要使用排它锁。
3、读操作能够控制他的处理的方式,写操作不能控制它的处理方式
隔离级别分为六种:
read uncommited(读取未提交数据),read commited(读取已提交数据)读取的默认方式,repeatable read(可重复读),serializable(可序列化),snapshot(快照),read commited snapshot(已经提交读隔离)(后两个是sql server 2005 里面 引入的)。隔离的强度依次递增。
&1、read uncommitted:
1 select * from [Sales.Shippers] where shipperid=3;
&查询结果:
在本线程内执行:
12 update [Sales.Shippers] set companyname='圆通' where shipperid=3;
在另外一个线程内 使用 read uncommitted 隔离级别 查询数据:
1 --设置读操作的隔离级别2 set transaction isolation le3 select * from [Sales.Shippers] where shipperid=3;
&查询结果:
如果这个时候将那个事务回滚,那么这个时候 &查询到的数据就是&脏数据&。
read uncommitted:最低的隔离级别:查询的时候不会请求共享锁,所以不会和排它锁产生冲突(不会等待排它锁执行完),查询效率非常高,速度飞快。但是缺点:会查到&脏数据&(排它锁的事务已经将数据修改,还没提交,这个时候查询到的数据 是已经更改过的。如果事务回滚,就是&脏数据&)
优点:查询效率非常高,速度非常快。
缺点:会产生&脏数据&
适用于 像聊天软件的 聊天记录,会是软件的运行速度非常快。 但是不适用于 商务软件。尤其是银行
2、read committed
&读取的默认隔离级别就是read committed 和上面正好相反。如果上面情况,采用read committed 隔离级别查询的话查到的就是还没有更改之前的数据。
&所以在这里就不再演示。
3、repeatable read:
&查询的时候会加上共享锁,但是查询完成之后,共享锁就会被撤销。比如一些购票系统,如果查到票了,当买的时候就没有,这是不行的。所以要在查询到数据之后做一些延迟共享锁,进而阻塞排它锁来修改。
在查询线程里面执行sql语句:
1 set transaction isolation l23 select * from [Sales.Shippers] where shipperid=4;
然后在 另外一个线程内执行修改语句:
update [Sales.Shippers] set companyname='shit' where shipperid=4;
这个时候会将更改的线程阻塞掉:
4、serializable(可序列化)
&更高级的 隔离。用户解决&幻读&。就是使用上面的 &加上共享锁 并不撤销,如果锁定的 一行数据,那么 其他的进程 还可以对 其他的数据进行操作,也可以 进行新增和删除的操作。 & 所以如果想要在查询的时候,不能对整张表进行任何操作,那么就要 将表的结构也 锁定 & &(就需要使用 更强的 锁定)
在查询线程执行sql语句:
1 set transaction isolatio2 34 select * from [Sales.Shippers] where shipperid=3;
那么在另外一个线程执行下面两个语句,不论那一条语句都会阻塞住:
update [Sales.Shippers] set companyname='联邦' where shipperid=3;insert into [Sales.Shippers] (companyname,phone) values('韵达','')
可序列话 隔离读操作:用户 解决 幻影数据(将标的数据和表的结构都锁定),是并发降低...隔离级别越高,并发越低,但是效率越低,所以不是要确定使用 &最好不要使用
下面两种隔离级别是在 sql server 2005才出现的,隔离级别更高:
5、snapshot(快照)
&为数据产生一个临时数据库,当sql server 数据更新之前将当前数据库复制到 tempdb数据库里面,查询就是从tempdb数据库中查询
--设置数据库支持快照隔离级别:alter database ssdemo set allow_snapshot_--这个时候会产生一个临时数据库(写操作的排它锁锁定的是 现实存在的数据库,,读操作的读取的是 临时数据库)
&在一个线程中执行 更新操作,用排它锁锁定当前数据
--使用 排它锁(独占锁)X,锁定 下面的那条数据update [Sales.Shippers] set companyname='飞凤' where shipperid=3;
这个时候在在另外一个线程中查询这条数据(默认的隔离级别),就会将当前线程阻塞。
如果使用 snapshot 隔离级别查询就不会阻塞。
1 set transaction isol2 --下面的就可以
从临时数据库中查询到数据34 --使用 共享锁 S5 select * from [Sales.Shippers] where shipperid=3;--查询到的 是还没有完成更新之前的数据
但是同时也会带来两个问题:
1、当 另外一个事务 &已经提交,但是这边的查询到数据还是没有修改。因为 每次查询到的快照是针对于 本次回话对应的那个 transaction 的,因为在这个事务里面是没有修改的,所以查询到的数据是没有修改的。
2、(更新问题)因为 那边的数据已经是 飞凤公司了,但是这里还是 & 联邦,所以,在这个事务里面是不能对表进行修改,因为访问的是临时数据库,想要对 数据库修改是不可能的(sql server 就会报错,阻止修改)&
针对于上面两个问题,所以下面 更高的隔离级别出现了 read committed snapshot:
6、read committed snapshot
&首先开启数据库的 read committed snapshot 隔离级别:
1 --设置 数据库 为 读取已经提交的快照 开启2 alter database ssdemo set read_committed_
在一个线程中执行:
update [Sales.Shippers] set companyname='联邦' where shipperid=3;
在另外一个线程中:
1 --不用显示声明使用
read committed snapshot 隔离级别,因为设置完 read_committed_snapshot 隔离级别启动,默认就是 read commited snapshot 隔离级别23 select * from [Sales.Shippers] where shipperid=3;--查询到是 已经提交之后的数据4 5 update [Sales.Shippers] set companyname='xiaoxiao' where shipperid=3;
这个时候查询到的数据是还没有更改之前的,如果将 前面的那个回话提交,那么在查询 查询到的数据是 提交修改之后的数据。所以解决了上面的问题1.
如果在修改的话。也是在第一个 更新线程中的事务更新之后的数据进行执行修改的操作,不会报错。
大家感兴趣的内容
12345678910
最近更新的内容}

我要回帖

更多关于 mysql 事务 意外中断 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信