关于J2EE中死锁问题的研究
http://tech.ddvip.com 2006年11月21日 社区交流
本文详细介绍关于J2EE中死锁问题的研究
基于数据库模式,读写操作会要求遍历或更新多个索引、验证约束、执行触发器等。每个要求都会引入更多锁。此外,其他应用程序还可能正在访问同一数据库模式中的某些对象,并获取不同于您的应用程序所具有的锁。
所有这些因素综合在一起,数据库死锁几乎不可能被消除了。值得庆幸的是,数据库死锁通常是可恢复的:当数据库发现死锁时,它会强制销毁一个连接(通常是使用最少的连接),并回滚其事务。这将释放所有与已经结束的事务相关联的锁,至少允许其他连接中有一个可以获取它们正在被阻塞的锁。
由于数据库具有这种典型的死锁处理行为,所以当出现数据库死锁问题时,数据库常常只能重试整个事务。当数据库连接被销毁时,会抛出可被应用程序捕获的异常,并标识为数据库死锁情况。如果允许死锁异常传播到初始化该事务的代码层之外,则该代码层可以只启动一个新事务并重做先前所有工作。要正确使用此策略,则在事务成功提交之前,它的代码不能有其他操作。注意:要限制重试次数,否则易导致死锁的代码块会永久循环下去。
如果出现问题就重试,这种方法有点笨。但是,由于数据库可以自由地获取锁,所以几乎不可能保证两个或两个以上的线程不发生数据库死锁。此方法至少能保证在出现某些罕见的数据库死锁情况时,应用程序能正常运行。这比要求用户去重试操作要好得多。
在J2EE应用程序中,开发人员可以设置一个EJB调用以使用Bean托管事务(BMT)——开发人员启动、提交或回滚特定的事务或容器托管事务(CMT)——调用方法前启动事务,并在方法完成后提交或回滚事务。如果EJB供应商提供retry-on-deadlock参数,从而可以通过容器托管事务自动完成此操作,那当然再好不过了。如果没有这种自动功能,开发人员最终将仅为了对死锁进行重试而强制EJB调用使用Bean托管事务。
来源:bea 作者:Michael Nonemacher 责编:豆豆技术应用