sybase锁机制以及死锁避免

在数据库实现中,通过锁定机制控制数据库的并发访问,保证数据库访问的正确性。根据定义:

锁定是一种并发控制机制:它可以确保数据在同一事务中和不同事务之间保持一致。在多用户环境中,由于几个用户可能会在同一时间使用同一数据,因此需要锁定功能。

sybase锁分类

按照锁性质可以分为共享锁,排他锁。当在数据库事务中,读取信息时,会对数据库添加共享锁。当修改信息时,会添加排他锁。

按照锁的粒度,可以分为行锁,页锁,表锁等。

sybase隔离级别

sybase分为0,1,2,3四个隔离级别。

0  读取未提交的,允许事务读取未提交的数据更改,排他锁在对数据库进行写操作后立即释放,不会持有到事务提交或回滚。
1 读取已提交的,仅允许事务读取已提交的数据更改,排他锁持有到事务提交或回滚,但共享锁在加载数据到内存后立即释放。
2 可重复读取事务可重复同一查询,事务读取过的任何行都不会被更新或删除,排它锁和共享锁都会持有到事务结束,查询结果集不可以删除和修改,但是可以插入。
3 可串行化读取事务可重复同一查询,且得到完全相同的结果。不能插入任何将出现在结果集中的行,排它锁和共享锁都会持有到事务结束,查询结果集不可以增删改。

可以使用select @@isolation语句查看数据库的隔离级别。

sybase数据库通常隔离界别设置为1,值得注意的是使用WAS通过jdbc连接数据库上,经常会将隔离级别提升为2。在使用E-SQL编译时,通常将隔离级别提升为3。

sybase死锁

sybase数据库出现死锁,即处于死锁中的各事务,都持有锁,但又都在等待其他锁,从而组成一个环,造成死锁。

最简单的死锁情况,事务T1,T2,执行顺序相反,会造成死锁,情形如下:

执行顺序

T1 T2
1 排他锁A  
2   排他锁B
3 排他锁B  
4   排他锁A

这时候,会出现事务T1持有排他锁A,同时等待排他锁B,事务T2持有排他锁B,等待排他锁A。这是就造成了T1等待T2释放排他锁B,T2等待T1释放排他锁A,形成一个死锁环。

多个事务出现死锁时,情形与两个事务死锁相比,只是环更大了一些,环上的节点多了一些。其本质仍然是形成一个等待环。

隔离级别对死锁的影响

隔离级别同样会对锁定有很大的影响,例如,

情形一、

执行顺序

T1 T2
1 排他锁A  
2   排他锁B
3 共享锁B  
4   共享锁A

当隔离级别为0时,不会出现死锁。当隔离界别为1,2,3时,则会发生死锁。

情形二、

执行顺序

T1 T2
1 共享锁A  
2   共享锁B
3 排他锁B  
4   排他锁A

当隔离级别为0,1时,不会出现死锁。当隔离界别为2,3时,会发生死锁。

情形三、

该情况是最近在系统中发现的一个死锁问题。程序从文件导入数据到数据库中,每次导入一条记录时,首先尝试以update的方式导入一条记录,当找到记录为空时,则将该条记录更改为以insert的方式导入到数据库中。

同时,导入过程是由多个进程共同完成的,每个进程导入一个文件,多个进程同时工作,然而当程序运行时,多个进程同时导入出现死锁。

通过监控sybase日志,发现死锁都是发生在insert时,出现next-key lock。sybase日志保存在安装目录下,例如安装目录为/sybase/ASE-12_5,日志文件为/sybase/ASE-12_5/install/db_name.log。

通过检查数据库的隔离级别,为1,没有发现异常,百思不得其解。

后在程序中添加查询数据库隔离级别语句,以检查在程序运行中到底隔离级别是多少?

经检查,隔离级别为3,也就是说在事务中,不能插入任何将出现在结果集中的行,下面分析一下出现死锁的原因。

当两个进程同时插入记录到同一个间隙中时,每个事务可能由两个操作组成

1.update

2.insert,当update结果集为空时,则转为insert。

其执行过程中,两个进程可能出现以下运行情况

执行顺序

T1 T2
1 共享锁A  
2   共享锁B
3 排他锁B  
4   排他锁A

例如,目前数据库只有一条记录,主键为5,此时T1,T2分别插入主键为3,4的数据,由于两个事务都在运行之中,因此T1,T2都会尝试在5之前插入数据,首先其在update时,会产生共享锁,由于隔离级别为3,此时两个事务尝试插入时都会失败,要解决这种死锁,可以在程序中显式设置隔离级别为1。

sybase锁升级

sybase同时提供锁升级的功能,例如将行锁升级为页锁,将页锁升级为行锁。具体参数可以进行设置。

例如当某一页中90%的行都被锁定,那么此时sybase可能将这些多个行锁升级为一个页锁,锁定整个页。这也是造成死锁一个重要的原因。

有时,根据判断,不会产生死锁。

执行顺序

T1 T2
1 行级排他锁A  
2   行级排他锁B
3 行级排他锁C  
4   行级排他锁D

在上述情况中,如果没有锁升级机制,是无论如何也不会产生死锁的。但是当有了锁升级机制之后,可能T1在将行级锁A升级为页锁Pa,T2将行锁B升级为页锁Pb,而T1需要访问的行C在页Pb中,T2需要访问的D在也Pa中,这时就会构成一个锁定环,构成死锁。

 

总结

在软件系统实现中,经常会采用数据库。使用数据库时死锁问题是大家通常都会遇到的,遇到死锁首先需要分析原因,定位问题,这也是最关键的一步。

出现死锁的原因很多,但本质一定是多个进程出现了相互等待,而每个进程又都持有锁,从而形成了一个依赖关系环,因此问题最关键的就是找到这个依赖关系,以及是哪几个事务,哪几个锁导致了死锁,只要确定了这几点,死锁问题将迎刃而解。

posted on 2010-07-15 11:03  谷底望月  阅读(2345)  评论(0编辑  收藏  举报

导航