DB2锁的兼容性是维护过程中时常会碰到的问题。下面会谈些相关情况,以及死锁的问题处理。
锁兼容性
如果数据资源上的一种锁状态允许在同一资源上放置另一个锁,就认为这两种锁(或两种状态)是兼容的。每当一个事务持有数据资源上的锁,而第二个事务请求同一资源上的锁时,DB2 数据库管理器检查两种锁状态以确定它们是否兼容。如果锁是兼容的,则将锁授予第二个事务(假定没有其它事务在等待该数据资源)。但是,如果锁不兼容,则第二个事务必须等待,直到第一个事务释放它的锁为止,然后才可以获取对资源的访问权并继续处理。(如果资源上有多个与新请求的锁不兼容的锁,则第二个事务必须等到它们全部被释放为止。)
锁升级
所有的锁都需要存储空间;因为可用空间并不是无限的,所以 DB2 数据库管理器必须限制锁可以使用的空间(这是通过 maxlocks 数据库配置参数完成的)。为了防止特定数据库代理超过已建立的锁空间限制,当获取的(任意类型的)锁过多时,会自动执行称为锁升级的进程。锁升级是一种转换,它将同一表内几个单独的行级锁转换成一个单独的表级锁。因为锁定升级是在内部处理的,所以唯一可从外部检测到的结果可能只是对一个和多个表的并发访问减少了。
以下是锁定升级的工作原理:当事务请求锁,而锁存储空间已满时,就选定与该事务相关联的一个表,帮它获取一个表级锁,释放所有该表的行级锁(以在锁列表数据结构中创建空间),并将表级锁添加到锁列表。如果这个过程所释放的空间不够,则选定另一个表,重复这个过程,直到释放了足够的可用空间为止。这时,事务将获取所请求的锁并继续执行。但是,如果在该事务的所有行级锁都已经升级之后,仍然没有获得必要的可用锁空间,则(通过 SQL 错误代码)要求事务提交或回滚它启动以来所作的所有更改,然后事务终止。
死锁
有时两个或更多个事务对锁的争用会引起称为死锁的情况。说明死锁发生原因的最佳方式是举例说明:假定事务 1 在表 A 上获取了互斥(X)锁,而事务 2 在表 B 上获取了互斥(X)锁。现在,假定事务 1 尝试在表 B 上获取互斥(X)锁,而事务 2 尝试在表 A 上获取互斥(X)锁。这两个事务的处理都将被挂起,直到同意第二个锁请求为止。但是,因为在任何一个事务释放它目前持有的锁(通过执行或回滚操作)之前,(两者中的)任一事务的锁请求都不会被同意,而且又因为两个事务都不能释放它目前持有的锁(因为它们都已挂起并等待锁),所以两个事务都陷入了死锁状况。
当死锁状况发生时,除非某些外部代理采取行动,否则所涉及的所有事务将无限期地等待释放锁。DB2 通用数据库用于处理死锁的工具是称为死锁检测器的异步系统后台进程。死锁检测器的唯一职责是定位和解决在锁定子系统中找到的任何死锁。死锁检测器在大多数时间处于休眠状态,但会在预置的时间间隔被“唤醒”,以确定是否存在死锁状况。如果死锁检测器在锁定子系统中发现死锁,则选择死锁涉及的一个事务、终止并回滚它。(被终止和回滚的事务收到一个 SQL 错误代码,它所获得的所有锁都被释放。)通常,剩下的一个或多个事务就可以继续执行了。
锁超时
任何时候当一个事务在特定数据资源(例如,表或行)上持有锁时,直到持有锁的事务终止并释放它所获取的所有锁之前,其它事务对该资源的访问都可能被拒绝。如果没有某种适当的锁超时检测机制,则事务可能无限期地等待锁的释放。例如,有可能出现这种情况:一个事务在等待另一个用户的应用程序所持有的锁被释放,而该用户离开了他(或她)的工作站,但忘了执行一些允许应用程序终止拥有锁的事务的交互。显然,此类情况会导致极差的应用程序性能。要避免发生此类情况时阻碍其它应用程序的执行,可以在数据库的配置文件中指定锁超时值(通过 locktimeout数据库配置参数)。使用之后,该参数就控制任何事务将等待获取所请求的锁的时间。如果在指定的时间间隔过去之后还未获得想要的锁,则等待的应用程序接收一个错误,并回滚请求该锁的事务。分布式事务应用程序环境特别容易产生此类超时;可以通过使用锁超时避免它们。
阅读(5566) | 评论(0) | 转发(0) |