数据库死锁的解决办法
数据库死锁处理方法

数据库死锁是指两个或多个事务在同时访问数据库时,因为资源竞争而导致的线程或进程的永久停滞现象。
死锁是数据库管理系统中常见的问题之一,它可能导致数据库系统性能下降或数据丢失。
常见的数据库死锁处理方法如下:
●预防性死锁:避免死锁发生的最佳方法是通过设计数据库系统来预防死锁。
●检测死锁:当死锁发生时,数据库管理系统应该能够检测到死锁并采取适当
的措施来解决问题。
●解除死锁:当死锁发生时,数据库管理系统应该能够找到死锁并采取适当的
措施来解决问题。
●中止事务:如果无法解除死锁,可以考虑中止其中一个或多个事务来解除死
锁。
●使用超时机制:在事务等待超过一定时间后自动中止事务,避免死锁的长时
间占用系统资源。
●使用锁粒度:缩小锁的粒度可以减小互相等待的可能性,减小死锁的发生。
数据库中解决死锁的常用方法

数据库中解决死锁的常用方法在数据库管理系统中,死锁是一种常见但麻烦的问题。
当多个事务同时请求数据库中的资源,并且这些资源被彼此占用,但是又无法相互释放时,就会发生死锁。
死锁的出现可能导致系统性能下降,甚至是数据库崩溃。
因此,解决死锁问题是数据库管理人员需要重视和解决的重要任务。
那么,在数据库中,有哪些常用的方法来解决死锁问题呢?下面将为大家介绍几种常见且有效的死锁解决方法。
第一种方法是通过设置超时时间来解决死锁。
当一个事务请求某个资源时,如果在规定的超时时间内无法获取到该资源,系统就会自动中断这个事务,并回滚所有已经执行的操作。
这种方法虽然简单,但是可能会引起一些业务问题,因为这样做会导致一些事务被中断,可能需要重新执行。
第二种方法是通过死锁检测来解决死锁。
这种方法通常通过算法来检测死锁,并且在检测到死锁时采取一些措施来解决它。
常见的死锁检测算法有银行家算法和图论算法。
这些算法可以在死锁发生时,找到导致死锁的事务,并且选择一个事务进行回滚,从而解除死锁。
但是,这种方法需要消耗系统资源,可能会影响数据库的性能。
第三种方法是通过锁粒度的优化来解决死锁。
将原本被一次性锁住的资源拆分为多个资源,可以降低死锁的概率。
例如,如果一个事务需要修改多个记录,可以将这些记录分开,分别为每个记录加锁。
这样做可以减少死锁的发生,但是也增加了系统的复杂性。
第四种方法是通过加锁顺序的优化来解决死锁。
如果多个事务都会请求相同的资源集合,可以约定一个统一的加锁顺序。
例如,可以规定按照资源的唯一标识符进行加锁,这样不同的事务就会按照相同的顺序加锁,避免了死锁的发生。
这种方法适用于事务之间需要访问多个资源的情况。
第五种方法是通过动态资源分配来解决死锁。
在数据库管理系统中,可以通过动态分配资源的方式来避免死锁。
例如,可以实时监测事务的资源请求情况,并根据当前系统情况来决定是否分配资源。
如果系统资源紧张,可以选择不分配资源,以避免死锁的发生。
数据库死锁的检查和解决方法

数据库死锁的检查和解决⽅法转⾃:数据库死锁的检查⽅法⼀、数据库死锁的现象程序在执⾏的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错。
⼆、死锁的原理当对于数据库某个表的某⼀列做更新或删除等操作,执⾏完毕后该条语句不提交,另⼀条对于这⼀列数据做更新操作的语句在执⾏的时候就会处于等待状态,此时的现象是这条语句⼀直在执⾏,但⼀直没有执⾏成功,也没有报错。
三、死锁的定位⽅法通过检查数据库表,能够检查出是哪⼀条语句被死锁,产⽣死锁的机器是哪⼀台。
1)⽤dba⽤户执⾏以下语句select username,lockwait,status,machine,program from v$session where sid in(select session_id from v$locked_object)如果有输出的结果,则说明有死锁,且能看到死锁的机器是哪⼀台。
字段说明:Username:死锁语句所⽤的数据库⽤户;Lockwait:死锁的状态,如果有内容表⽰被死锁。
Status:状态,active表⽰被死锁Machine:死锁语句所在的机器。
Program:产⽣死锁的语句主要来⾃哪个应⽤程序。
2)⽤dba⽤户执⾏以下语句,可以查看到被死锁的语句。
select sql_text from v$sql where hash_value in(select sql_hash_value from v$session where sid in(select session_id from v$locked_object))四、死锁的解决⽅法⼀般情况下,只要将产⽣死锁的语句提交就可以了,但是在实际的执⾏过程中。
⽤户可能不知道产⽣死锁的语句是哪⼀句。
可以将程序关闭并重新启动就可以了。
经常在Oracle的使⽤过程中碰到这个问题,所以也总结了⼀点解决⽅法。
1)查找死锁的进程:sqlplus "/as sysdba" (sys/change_on_install)SELECT ername,l.OBJECT_ID,l.SESSION_ID,s.SERIAL#,l.ORACLE_USERNAME,l.OS_USER_NAME,l.PROCESSFROM V$LOCKED_OBJECT l,V$SESSION S WHERE l.SESSION_ID=S.SID; 2)kill掉这个死锁的进程: alter system kill session ‘sid,serial#’; (其中sid=l.session_id) 3)如果还不能解决:select pro.spid from v$session ses,v$process pro where ses.sid=XX andses.paddr=pro.addr; 其中sid⽤死锁的sid替换:exitps -ef|grep spid 其中spid是这个进程的进程号,kill掉这个Oracle进程。
数据库事务处理中的死锁检测与解决方案

数据库事务处理中的死锁检测与解决方案死锁是在并发环境下经常会出现的一个问题,特别是在数据库事务处理中。
当多个事务同时竞争资源时,可能会出现死锁现象,导致系统无响应或运行缓慢。
因此,在数据库事务处理中,死锁的检测和解决方案变得尤为重要。
一、死锁的定义与原因死锁,顾名思义,即两个或多个事务互相等待对方所持有的资源,无法继续执行下去。
死锁的产生通常有以下四个必要条件:1. 互斥条件:资源只能同时被一个事务占用。
2. 请求与保持条件:一个事务在持有一部分资源的同时,又请求其他资源。
3. 不可剥夺条件:资源只能由持有者显式释放,不能被其他事务强制剥夺。
4. 循环等待条件:存在一个循环等待的事务链,每个事务都在等待其他事务所占用的资源。
二、死锁的检测方法在数据库系统中,有几种常用的死锁检测方法,如以下两种:1. 策略1:等待图等待图是一种用于检测和解决死锁的算法。
它是通过判断事务之间的互斥关系,并记录事务之间的等待关系来构建的。
如果在等待图中存在一个环路,那么就可以判断系统产生死锁了。
2. 策略2:超时机制超时机制是在进行资源申请的同时,为每个事务设置一个超时时间。
如果某个事务在等待时间过长后仍然无法获取资源,则自动放弃对该资源的请求,可以避免死锁的发生。
但是,这种方式可能会引起资源浪费,因为一个事务可能因为资源不足而频繁地放弃请求。
三、死锁的解决方案在数据库事务处理中,常用的死锁解决方案主要包括以下几种:1. 策略1:死锁预防死锁预防是一种通过确保死锁的四个必要条件之一不能同时出现来解决死锁问题的方法。
常用的死锁预防方法包括:- 资源有序分配(Resource Ordering):为资源分配一个全局的顺序,然后按照这个顺序请求,降低出现循环等待的可能性。
- 一次只申请一个资源(One at a Time):事务在执行过程中,一次只请求一个资源,使用完成后立即释放,并且事务之间严格按照资源的访问顺序进行请求,从而避免了循环等待的情况。
数据库死锁的产生与解决方法

数据库死锁的产生与解决方法数据库作为现代信息系统的核心组成部分之一,承担着存储和管理大量数据的重要任务。
然而,在多用户并发访问数据库时,死锁问题可能会导致系统性能下降甚至崩溃。
本文将探讨数据库死锁的产生原因,以及常用的解决方法。
一、死锁的产生原因1. 互斥访问资源:死锁的产生是因为多个并发事务同时竞争访问同一资源,每个事务都要求独占资源,但资源无法同时满足所有请求,导致事务之间发生资源竞争。
2. 内存不足:当系统内存不足时,数据库管理系统可能会将一些数据和操作转移到虚拟内存中。
如果产生死锁并且没有充足的物理内存来满足事务需求,那么死锁就会发生。
3. 事务持有和等待:当一个事务获取一个资源时,它可能会继续请求其他资源,并在等待其他资源的同时持有已获取的资源。
如果其他事务需要这些已获取的资源,则会产生死锁。
4. 循环等待:多个事务形成环形等待资源的关系,每个事务都在等待下一个事务所持有的资源,导致死锁的产生。
二、死锁解决方法1. 死锁检测与恢复:死锁检测算法可以周期性地扫描系统,定期检查是否存在死锁。
一旦检测到死锁,可以使用死锁恢复算法将死锁事务进行回滚,释放资源,解除死锁状态。
2. 死锁预防:死锁预防方法旨在通过改变系统的策略和规则,防止死锁的发生。
常见的预防方法包括:- 破坏互斥条件:通过将资源设置为可共享而不是互斥性的,可以防止死锁的发生。
- 破坏占有和等待条件:要求一个事务在执行之前获取所有需要的资源,而不是持有部分资源后再去请求其他资源。
- 破坏不可抢占条件:允许系统抢占一些资源,以便在发生死锁时能够打破死锁链。
- 破坏循环等待条件:通过强制事务按照某种统一顺序来请求资源,避免循环等待。
3. 死锁避免:死锁避免方法在事务执行之前对事务进行检测,并根据预测的执行路径来避免潜在的死锁情况。
该方法需要提前获得事务的请求资源信息,以便进行检测和判断是否应该阻止某个事务。
避免死锁的常用算法包括银行家算法和资源分配图算法。
数据库死锁问题及解决方法

数据库死锁问题及解决⽅法什么是数据库死锁每个使⽤关系型数据库的程序都可能遇到数据死锁的情况。
理解什么是死锁之前先要了解锁定的概念:如果需要“修改”⼀条数据,⾸先数据库管理系统会在上⾯加锁,以保证在同⼀时间只有⼀个事务能进⾏修改操作。
锁定(Locking)发⽣在当⼀个事务获得对某⼀资源的“锁”时,这时,其他的事务就不能更改这个资源了,这种机制的存在是为了保证数据⼀致性。
多数情况下,可以认为如果⼀个资源被锁定,它总会在以后某个时间被释放。
⽽死锁发⽣在当多个进程访问同⼀数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都⽆法继续下去。
简单的说,进程A等待进程B释放他的资源,B⼜等待A释放他的资源,这样就互相等待就形成死锁。
导致数据库死锁的原因⼀般情况只发⽣锁超时,就是⼀个进程需要访问数据库表或者字段的时候,另外⼀个程序正在执⾏带锁的访问(⽐如修改数据),那么这个进程就会等待,当等了很久锁还没有解除的话就会锁超时,报告⼀个系统错误,拒绝执⾏相应的SQL操作。
发⽣死锁的情况⽐较少,⽐如⼀个进程需要访问两个资源(数据库表或者字段),当获取⼀个资源的时候进程就对它执⾏锁定,然后等待下⼀个资源空闲,这时候如果另外⼀个进程也需要两个资源,⽽已经获得并锁定了第⼆个资源,那么就会死锁,因为当前进程锁定第⼀个资源等待第⼆个资源,⽽另外⼀个进程锁定了第⼆个资源等待第⼀个资源,两个进程都永远得不到满⾜。
数据库死锁的解决⽅案use master --必须在master数据库中创建2go34if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_lockinfo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)5drop procedure [dbo].[p_lockinfo]6GO78/**//*--处理死锁910 查看当前进程,或死锁进程,并能⾃动杀掉死进程1112 因为是针对死锁的,所以如果有死锁进程,只能查看死锁进程13 当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程1415 感谢: caiyunxia,jiangopen 两位提供的参考信息1617--邹建 2004.04(引⽤请保留此信息)--*/1819/**//*--调⽤⽰例2021 exec p_lockinfo22--*/23create proc p_lockinfo24@kill_lock_spid bit=1, --是否杀掉死锁的进程,1 杀掉, 0 仅显⽰25@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显⽰正常进程信息,1 显⽰,0 不显⽰26as27set nocount on28declare @count int,@s nvarchar(1000),@i int29selectid=identity(int,1,1),标志,30 进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,31 数据库名=db_name(dbid),⽤户ID=uid,⽤户名=loginame,累计CPU时间=cpu,32 登陆时间=login_time,打开事务数=open_tran, 进程状态=status,33 ⼯作站名=hostname,应⽤程序名=program_name,⼯作站进程ID=hostprocess,34 域名=nt_domain,⽹卡地址=net_address35into #t from(36 select 标志='死锁的进程',37spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,38status,hostname,program_name,hostprocess,nt_domain,net_address,39 s1=a.spid,s2=040 from master..sysprocesses a join (41 select blocked from master..sysprocesses group by blocked42 )b on a.spid=b.blocked where a.blocked=043 union all44 select '|_牺牲品_>',45 spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,46status,hostname,program_name,hostprocess,nt_domain,net_address,47 s1=blocked,s2=148 from master..sysprocesses a where blocked<>049)a order by s1,s25051select@count=@@rowcount,@i=15253if @count=0 and @show_spid_if_nolock=154begin55 insert #t56 select 标志='正常的进程',57spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,58open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address59 from master..sysprocesses60 set @count=@@rowcount61end6263if @count>064begin65 create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))66 if@kill_lock_spid=167 begin68 declare @spid varchar(10),@标志 varchar(10)69 while@i<=@count70 begin71 select @spid=进程ID,@标志=标志 from #t where id=@i72 insert #t1 exec('dbcc inputbuffer('+@spid+')')73 if @@rowcount=0 insert #t1(a) values(null)74 if @标志='死锁的进程' exec('kill '+@spid)75 set @i=@i+176 end77 end78 else79 while @i<=@count80 begin81 select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i82 insert #t1 exec(@s)83 if @@rowcount=0 insert #t1(a) values(null)84 set @i=@i+185 end86 select a.*,进程的SQL语句=b.EventInfo87 from #t a join #t1 b on a.id=b.id88 order by 进程ID89end90set nocount off91go。
数据库表锁死的解决方法

数据库表锁死的解决方法
数据库表锁死通常是指表级别的锁被占用,其他表中的数据无法访问的情况。
常见的解决方法有以下几种:
1. 重试锁:在锁定期间,可以不断地尝试获取锁,直到成功获取锁为止。
这种方法可以强制释放被占用的锁,使得其他表可以访问到受影响的数据。
2. 并发锁:将锁分配给并发事务,以便多个事务同时访问同一个表时,可以使用并发锁来避免竞争条件。
但是,这种方法可能会降低性能,因为多个事务需要同时等待锁。
3. 数据库级别的锁定限制:在数据库中设置锁定限制,使得可以限制对同一表的锁定时间或锁定数量等。
这种方法可以更加精确地控制锁的使用,避免锁死的问题。
4. 数据库操作日志:记录数据库操作日志,以便在出现锁死问题时,可以追溯锁定的来源和原因。
通过分析操作日志,可以找到锁死的根本原因,并采取相应的措施解决。
5. 数据库性能优化:优化数据库的性能和架构,降低锁的使用,减少锁死的可能性。
需要注意的是,解决锁死问题需要根据具体情况进行综合考虑,采取多种方法的组合来解决。
同时,解决锁死问题也需要遵守锁的使用规范,避免锁的使用不当导致锁死的问题。
数据库死锁问题分析与解决步骤解读

数据库死锁问题分析与解决步骤解读当多个并发的事务同时请求数据库中的资源时,可能会发生死锁现象。
数据库死锁是一个常见的问题,它会导致系统性能下降甚至完全停止响应。
因此,有效地解决和预防数据库死锁问题对于保证系统的稳定性和可靠性非常重要。
本文将详细介绍数据库死锁问题的分析与解决步骤。
一、死锁问题的概念与原因1.死锁概念:数据库死锁是指两个或多个事务彼此等待对方释放所占资源,从而无法继续执行下去的情况。
当一个事务锁定了某个资源,并请求另一个事务已经锁定的资源时,就可能发生死锁。
2.死锁原因:死锁通常由以下四个条件引起:(1)互斥:资源必须互斥地分配给事务,即每个资源一次只能由一个事务占用。
(2)持有并等待:一个事务可以持有一个或多个资源,并同时请求另一个已被其他事务所占用的资源。
(3)不可抢占:资源只能由占有者显式地释放,无法被其他事务抢占。
(4)循环等待:多个事务之间存在一个循环等待资源的序列。
二、数据库死锁的解决步骤1.检测死锁:第一步是确认系统中是否存在死锁。
可以使用系统自带的死锁检测工具或者编写自定义的监控程序来检测死锁。
死锁检测工具可以实时地监控系统的资源分配和请求情况,并进行死锁检测。
2.定位死锁:一旦系统检测到死锁,第二步是定位死锁。
通过分析死锁的日志和相关的系统信息,可以确定死锁的事务和资源。
3.解除死锁:一旦死锁被确认并定位,就需要解开死锁。
常用的死锁解除方法包括:(1)资源剥夺法:选择一个或多个事务,并强制终止其占用的资源,直到死锁被解除为止。
这种方法会造成部分事务的回滚以及数据的丢失,因此在使用时需要谨慎。
(2)撤销事务法:选择一个或多个事务,并进行回滚操作,使其释放所占用的资源。
这种方法会导致一部分数据回滚,但相较于资源剥夺法,对于数据的丢失会更少一些。
(3)资源预防法:通过设定适当的资源申请顺序,可以避免死锁的发生。
在编写事务的时候,需要明确指定事务申请资源的顺序,遵循相同的顺序来申请资源可以有效地避免死锁。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Posts - 31 Articles - 0 Comments - 817 数据库死锁的解决办法近日在博客网站上,回复别人的数据库死锁避免问题,之前也曾经几次答复过同样的内容,觉得很有必要汇聚成一个博客文章,方便大家。
这里的办法,对所有的数据库都适用。
这个解决办法步骤如下:1. 每个表中加updated_count (integer) 字段2. 新增一行数据,updated_count =0 :insert into table_x (f1,f2,...,update_count) values(...,0);3. 根据主键获取一行数据SQL,封装成一个DAO 函数(我的习惯是每个表一个uuid 字段做主键。
从不用组合主键,组合主键在多表join 时SQL 写起来很麻烦;也不用用户录入的业务数据做主键,因为凡是用户录入的数据都可能错误,然后要更改,不适合做主键)。
select * from table_x where pk = ?4. 删除一行数据4.1 先通过主键获取此行数据, 见3.4.2 delete from table_x where pk = ? and update_count=? , 这里where 中的update_count 通过4.1 中获取4.3 检查4.2 执行影响数据行数,如果删除失败,则是别人已经删除或者更新过同一行数据,抛异常,在最外面rollback,并通过合适的词语提醒用户有并发操作,请稍候再试。
int count = cmd.ExecuteNonQuery();if(udpatedCount < 1){throw new Exception(“检测到并发操作,为防止死锁,已放弃当前操作,请稍候再试,表xxx, 数据key ….”);}5. 更新一行数据5.1 先通过主键获取此行数据, 见3.5.2 update table_x set f1=?,f2=?, ...,update_count=update_count+1 where pk = ? and updat e_count=? , 这里where 中的update_count 通过5.1 中获取5.3 检查5.2 执行影响数据行数,如果更新失败,则是别人已经删除或者更新过同一行数据,抛异常,在最外面rollback,并通过合适的词语提醒用户有并发操作,请稍候再试。
int count = cmd.ExecuteNonQuery();if(udpatedCount < 1){throw new Exception(“检测到并发操作,为防止死锁,已放弃当前操作,请稍候再试,表xxx, 数据key ….”);}6. 数据库访问层DAO 中,绝对不要写try catch,也不要写commit/rollback. 因为当我写了一个dao1.insert(xxx) ,另一个人写了dao2.insert(xxx), 两周后有可能会有人把这两个函数组合在一起放在一个事务中。
如果dao1.insert(xxx)已经commit ,那么dao2.insert(xxx) 中rollback 会达不到期望效果。
很多电脑书中示例代码,都有这个错误。
数据库事务应该是这样界定起始范围:6.1 单机版程序,每个按钮操作,对应一个事务。
可以在把connection/transaction 传递到dao 中。
在按钮响应的代码处,处理事务。
catch 到任何Exception 都要rollback.6.2 网页版程序,每个按钮操作,对应一个事务。
可以在把connection/transaction 传递到dao 中。
在按钮响应的代码处,处理事务。
我强烈建议对于Web应用,数据库连接的打开/关闭、数据库事务的开始和commit/rollback 全在filter 中处理(Java EE 和 MVC 都有filter, 其它的不知道),事务、数据库连接通过threadlocal 传入到DAO 中。
filter 中catch 到任何Exception 都要rollback.见过很多用Spring 的人,代码中启动了几个数据库事务自己都不知道,符不符合自己的需要,也不知道。
我的建议是,禁止使用Spring 管理数据库事务。
7. 单表的增、删、改、通过主键查,应该用工具自动生成。
自动生成代码,应该放在单独一个目录,以便后面有数据库表改动,可以重新生成代码并覆盖。
自动生成的文件,在第一行就写上注释,表示这是一个自动生成的文件,以后会被自动覆盖,所以不要改这个文件。
举例来说,对于tm_system_user 表,可以自动生成TmSystemUserDAO, 包含函数: insert(TmSys temUser), update(TmSystemUser), delete(TmSystemUser), getByKey(key), batchInsert(TmSyste mUser[])。
8. 总是使用事务,并用ReadCommited 级别,即使是纯查询SQL,也这么写。
这可以简化设计与写代码,没有发现明显多余的性能消耗。
9. 数据设计时,尽量避免update/delete. 举例来说,如果是一个请假条的审批流程,把请假条申请设计成一个表,领导批复设计成另一个表。
尽量避免设计时合并成一个表,把批准状态(同意/否决)、批准时间当成“请假条申请”的属性。
说极端一点,最好从数据库设计上,避免后续编程有update/delete,只有insert。
好像现在流行的NoSQL 也是这么个思路。
10. 补充,如果在后台检查页面录入数据,报错处理,有以下两种方法:10.1 只要有一个错误,就throw exception.10.2 把所有的错误都检测出来,比如,用户名未录入,电子邮件未录入,放在一个List中,然后t hrow exception.2012-3-30, 由于很多网友对数据库死锁了解不深,甚至有部分网友,不知道数据库会死锁僵住,特补充一些资料。
以下内容,节选自《LINQ实战》:8.1.1悲观式并发在.NET出现之前,很多应用程序都需要自行管理与数据库之间的连接。
在这些系统中,开发人员经常在获取某条记录之后为其加锁,用来阻止其他用户可能在同时作出的修改。
此类加锁的策略就叫做悲观式并发。
悲观式并发对于某些小型的Windows桌面程序来讲可能没有什么问题,不过若是在用户很多的大型系统中使用同样的策略,那么系统的整体性能很快就会被拖累下来。
随着系统规模的扩大,可伸缩性问题开始浮出水面。
因此,很多系统从客户端-服务器架构迁移到了更少状态信息的、基于Web的应用程序,这也同时降低了部署的成本。
无状态的Web应用程序也让过于保守的悲观式并发策略再无用武之地。
为了让开发者避免陷入到悲观式并发所带来的可伸缩性以及加锁的泥沼中,.NET Framework在设计之初就考虑到了Web应用程序的离线特性。
.NET以及所提供的API均无法锁住某张数据表,这样自然就终结了悲观式并发的可能。
不过如果需要的话,应用程序同样能在第一次获取某条记录的同时为其添加一个"签出"标签,这样在第二次尝试访问时,即可获得该"签出"情况,并根据需要进行相应的处理。
不过很多情况下,由于很难确定用户是否不再使用这个标签,因此"签出"标签会经常处于未重新设置状态。
正因为这样,悲观式并发在离线程序中的使用频率也越来越低。
8.1.2乐观式并发由于离线环境下的程序常常不适合使用悲观式并发,因此另一种处理的策略,即乐观式并发逐渐出现在人们的视线中。
乐观式并发允许任意多的用户随时修改他们自己的一份数据的拷贝。
在提交修改时,程序将检查以前的数据是否有所改变。
若没有变化,则程序只需保存修改即可。
若发生了变化并存在冲突,那么程序将根据实际情况决定是将前一修改覆盖掉,还是把这一次新的修改丢弃,或是尝试合并两次修改。
乐观式并发的前一半操作相对来说比较简单。
在不需要并发检查的情况下,数据库中使用的SQL语句将类似于如下语法:UPDATE TABLE SET [field = value] WHERE [Id = value]。
不过在乐观式并发中,WHERE子句将不只包含ID列,同时还要比较表中其他各列是否与原有值相同。
在代码清单8-1中,我们在最后通过检查RowCount来查看这次更新是否成功。
若RowCount为1,则表明原有记录在该用户修改的期间并没有被别人更新,即更新成功。
若RowCount为0,则意味着有人在期间修改了该记录。
此时该记录将不会被更新,程序也能够告知用户有关该冲突的信息,并根据需要执行合适的操作...2012-3-31 补充:Oracle中的TimeStamp(时间戳)与SqlServer中的差别很大。
SqlServer中的TimeStamp是二进制格式存储在数据库中,可以将DataSet中的这个字段类型设定为base64Binary类型。
Oracle中的Time Stamp是时间格式存储的。
SQL Server 有个函数名叫CURRENT_TIMESTAMP,与SqlServer中的TimeStamp 数据列类型,没有一毛钱的关系。
个人认为SqlServer中的TimeStamp 数据列类型,属于“名词乱用”,与一般人理解中的timestamp 不是一个意思。
继续从互联网上查找,果然有发现:Transact-SQL timestamp 数据类型与在SQL-92 标准中定义的timestamp 数据类型不同。
SQL-92 timestamp 数据类型等价于Transact-SQL datetime 数据类型。
Microsoft SQL Server 将来的版本可能会修改Transact-SQL timestamp 数据类型的行为,使它与在标准中定义的行为一致。
到那时,当前的timestamp 数据类型将用rowversion 数据类型替换。
Microsoft SQL Server 2000 引入了timestamp 数据类型的rowversion 同义词。
在DDL 语句中尽可能使用rowversion 而不使用timestamp。
rowversion 受数据类型同义词行为的制约。
没有看出SQL Server timestamp 和数据库死锁有何关系!!!即使是微软LINQ for SQL 自动生成的代码,也是没有用到timestamp ,而是用了本博客文章中的技术。
如有哪位网友提供资料,说明 SQL Server timestamp 和数据库死锁有点关系,将不胜感谢。