日期:2014-05-18  浏览次数:20663 次

如何在sql server中更好的实现并发控制
关于这一点,到网上找过很多资料,个人总结一下:好像解决方案有以下三点:
一 : 对表进行手动加锁 ,像这样:
SQL code
SELECT * FROM table WITH (TABLOCKX)


二: 设置隔离级别实现并发控制,如下所示:
SQL code
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 


三:使用时间戳
每一次对数据库做更新时都要留下TIMESTAMP, 修改之前要取得TIMESTAMP, 提交时要比较数据的TIMESTAMP, 如果不同则停止处理, 向用户提示在他操作期间, 他所看到的数据已经被他人改动过了

我想问的有两点
一 : 除了这三点,还有没有什么解决方案?

二: 如果这几种是常用的解决方案那么在实际的开发中,哪种运用的比较多?还是说要看情况来或者几种结合在一起使用?
对这方面了解的不多,还望各位前辈不吝赐教

------解决方案--------------------
锁和隔离级别是需要的 时间戳没发现有多好用
------解决方案--------------------
一般是用设置事务隔离等级的方法.

------解决方案--------------------
SQL code

事物和并发性
在学习事物和并发性之前首先来理解两个概念:
1、什么事事物?
事物是SQL Server中的基本工作单元。通常它由几个读取和更新数据库的SQL命令组成,但是这些操作都不被看为最终的,直到发出一个COMMIT命令为止。
2、什么是并发性?
并发性可以定义为多个进程在相同时间访问或者更改共享数据的能力。既然是能力,那么一个系统的并发性就会有强弱之分。既然如此,我们该怎样判断一个系统并发行的强弱呢?
一般情况而言,一个系统在互不干扰的情况下可以激活的并发用户的进程数越多,该系统的并发性就越强。
可能影响并发性的一些原因分析:
当正在更改数据的进程阻止其他进程读取该数据时,或者当读取数据的进程阻止其他进程更改该数据时,并发行会减弱。另外,当多个进程试图同时更改相同数据时,且无法在不牺牲数据的一致性的前提下都能成功时,并发性也会受到影响。对于并发性的理解我们和容易联想到铁道部的订票网站。由于处理并发性能力不够,导致订票高峰出现奔溃现象,对网络订票造成不良影响。由此可见,一个大型网站的数据库系统提高处理并发性的能力是在必要。

处理并发性的方法:
SQL Server 2008提供两种方法:乐观和悲观两个模型。我们可以通过一下命令来指定:
SET TRANSACTION ISOLATION LEVEL(事物的隔离级别)来指定。
两者的区别:
在两种模型中,两个进程试图在相同时间修改相同数据时,可能会出现冲突。那么这两个模型之间的区别在于冲突是在出现前被避免还是在出现后采取某种方式进行处理。
悲观并发模型:
对于悲观并发SQL Server默认的行为是获取锁来阻塞对另一个进程正在使用的数据的访问。悲观并发假设系统中有足够的数据修改操作,因而给定的任何一个读写操作都可能受到另外一个用户的数据修改操作的影响。悲观并发通过获得正在被读取数据上的锁,使其他进程无法修改该数据而避免冲突。换言之,在悲观模型下,读取者阻塞写入者,写入者也阻塞读取者。

乐观并发模型:
乐观并发假设系统中有足够少的数据修改操作,因而任何单个事物都不太可能另一个事物正在修改的数据。乐观并发的默认行为是使用行版本控制来允许数据读取者看到修改之前的数据状态。数据行教老的版本被保存,所以读取数据的进程可以看到进程开始读取时的数据,不会受到对该数据正在做出任何更改的进程的影响。换言之,读取者不阻塞写入者,写入者也不阻塞读取者,但是,写入者可以而且会阻塞写入者,这也是导致冲突的原因所在。这时SQL Server在冲突出现时产生一个错误信息,但是是由应用程序来负责影响该错误。

事务处理:
ACID属性
原子性:原子性保证每个事物被作为整体单元被处理或者不被处理,要么全部处理,要么全部不处理:
例如:
以下事物模拟银行转帐
Begin trabsaction tran1
Update tb
set account=account+100  where accountid=’a’
updatet tb
set account=account-100 where accounted=’b’
Commit transaction tran1
以上简单的事物tran1中的两条语句要么都插入成功,要么都失败,不存在一条成功一条失败的现象。
换句话说,原子性保证了事物内部的所有语句被看作为一个原子,而原子是不可被分割的。
一致性:一致性确保事物不会允许系统达到不正确的逻辑状态。即使出现系统故障,也遵循所有的约束和规则。
例如上面的模仿银行转账的事物,事物的一致性确保了在a账户增加100远的同时b账户减少100元。避免了当a账户增加100后,系统出现故障而造成的b账户没有减少相应的资金。这确保了数据的一致性。
隔离性:隔离性将并发事物与其他未完成的事务的更新隔离开来。在上面的例子中,另一个事物无法看到这个正在执行的事物中所进行的工作。
持久性:在事物提交后,SQL Server的持久性属性确保事务的效果持久存在,即使出现系统故障亦是如此。
事物的依赖性
丢失更新:当两个进程读取相同数据,并且都操作数据,更改他的值,还试图将原始数据更新到新值,会出现数据丢失。例如:
A,B两个店员都接收到运来的部件。他们检查当前库存,并且看到存货当中还有25个部件。店员A收到的货是50个部件,所以他将50+25写入当前库存。店员B收到的是25个部件,所以他将20+25写入到数据库,覆盖了A添加的50个,这样就出现了数据更新丢失
脏读:脏读出现在进程读取未提交数据时。例如:A店员将原来的25个部件更新为75,在他提交之前,一个销售人员看到当前库存是75,并答应第二天给客户发60个部件。如果店员A发现这批零件中有缺陷,并且返回给供应商,并将库存更新为25,实际上就是销售人员进行了一次脏读,并基于未提交数据采取行动。默认情况下脏读是不允许的。
注意:更新数据的进程无法控制另一个进程是否可以在第一个进程提交之前读取他的数据。而是由读取数据的进程来决定它是否要读取不能保证已经提交的数据。
不可重复度:如果进程同一事物两次独立的读操作中读取相同的数据取得到不同的值,那么这样的读是不可重复的。

幻读:

事物的隔离级别:
未提交读:
已提交读:
可重复度:
快照:
可序列化:
每种隔离级别中允许的行为,如下表:
隔离级别    脏读    不可重复度    幻读    并发控制
未提交读    Y    Y    Y    悲观
已提交读(锁定)    N    Y    Y    悲观
已提交读(快照)    N    Y    Y    乐观
可重复度    N    N    Y    悲观
快照    N    N    N    乐观
可序列化    N    N    N    悲观
注:以上表格中的Y代表可以,N代表不可以

------解决方案--------------------
探讨

引用:
一般是用设置事务隔离等级的方法.

那为什么不使用给数据库加锁的方法呢?是为了预防死锁,还是什么别的原因?

------解决方案--------------------
1,2用的多,3没见到过使用比较好的场景。 

另外,1,2慎用。提示加锁的方式,有时候会有一些想不到的问题发生。

------解决方案--------------------