首页  编辑  

死锁


死锁

当一个进程锁定了另一个进程需要的页或者表的时候,而第二个进程又锁定了第一个进程需要的一页,这个时候就会发生死锁。死锁也叫抱死。SQL Server自动探测和解决死锁。如果找到一个死锁,服务器将终止完成了抱死的用户进程。

在每次数据修改之后,你的程序代码需要检查1205号消息,这个消息指出一个死锁。如果返回这个消息,就说明发生了一个死锁并且事务已经后滚。在这种情况下,你的应用程序必须重新开始这个事务。

死锁一般可以通过一些简单的技术加以避免:

  • 在你的应用程序的各部分以同样的顺序访问表。
  • 在每个表上使用分簇的索引以强制一个显式的行顺序。
  • 使事务简短。

远程事务

在Oracle中执行远程事务,你必须通过一个数据库连接访问远程数据库节点。在SQL Server中,你必须访问一个远程服务器。远程服务器是一台运行SQL Server的服务器,用户可以用他们的本地服务器访问该服务器。当某个服务器被设置为远程服务器,用户就可以在其上使用系统过程和存储过程而不需要显式的登录到上面。

远程服务器是成对设置的。你必须配置两台服务器,使它们互相把对方当作远程服务器。每台服务器的名字都必须用sp_addlinkedserver系统存储过程或者SQL Server Enterprise Manager加到伙伴服务器上。

设置完远程服务器以后,你可以用sp_addremotelogin系统存储过程或者SQL Server Enterprise Manager来为那些必须访问远程服务器的用户设置远程登录账号。在这一步完成以后,你还必须赋予他们执行存储过程的权限。

然后用EXECUTE语句来在远程服务器上执行过程。这个例子在远程服务器STUDSVR1上执行了validate_student存储过程,并且将指明成功或者失败的返回情况存储在@retvalue1中:

DECLARE @retvalue1 int

EXECUTE @retvalue = STUDSVR1.student_db.student_admin.validate_student '111111111'

欲了解详细信息,请参看SQL Server联机手册。

分布事务

如果修改两个或者更多的数据库节点上的表,Oracle就自动初始化一个分布式事务。SQL Server分布式事务使用包含在SQL Server中的微软分布事务协调器(Microsoft Distributed Transaction Coordinator,MS DTC)中的两步提交服务(two-phase commit services)。

缺省情况下,SQL Server必须被通知参与分布事务。SQL Server参与一个MS DTC事务可以用下面方式中的任一种来存储:

  • BEGIN DISTRIBUTED TRANSACTION语句。该语句开始一个新的MS DTC事务。
  • 一个客户端应用程序直接调用DTC事务接口。

在下例中,注意对本地表GRADE和远程表CLASS的分布式更新(使用一个class_name过程):

BEGIN DISTRIBUTED TRANSACTION

UPDATE STUDENT_ADMIN.GRADE

    SET GRADE = 'B+' WHERE SSN = '111111111' AND CCODE = '1234'

DECLARE @retvalue1 int

EXECUTE @retvalue1 = CLASS_SVR1.dept_db.dept_admin.class_name '1234',     'Basketweaving'

COMMIT TRANSACTION

GO

如果程序不能完成事务,则通过ROLLBACK TRANSACTION语句终止该事务。如果程序失败或者参与的资源管理器失败,MS DTC终止该事务。MS DTC不支持分布式的存储点或者是SAVE TRANSACTION语句。如果一个MS DTC事务失败或者后滚,则整个事务退回到分布式事务的起点,而不理会任何存储点。

两步提交处理

Oracle和MS DTC两步提交机制在操作上是相似的。在SQL Server两步提交的第一步,事务管理器请求每一个参与的资源管理器准备提交。如果有任何资源管理器没有准备好,事务管理器就向与事务相关的所有成员广播一个异常中断决定。

如果所有的资源管理器都能成功的准备,事务管理器就广播一个提交决定。这是提交处理的第二步。当一个资源管理器准备好后,事务究竟是提交了还是失败了,这一点还是拿不准。MS DTC维持了一个连续的日志,因此它的提交或者中断决定都是持久的。如果某个资源管理器或者事务管理器失败了,则当它们重新连接上的时候,就能在那个拿不准的事务上协调了。

image007.gif (3.3KB)