Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5473416
  • 博文数量: 890
  • 博客积分: 12876
  • 博客等级: 上将
  • 技术积分: 10760
  • 用 户 组: 普通用户
  • 注册时间: 2004-10-04 14:18
个人简介

猝然临之而不惊,无故加之而不怒。

文章分类

全部博文(890)

文章存档

2016年(1)

2014年(18)

2013年(41)

2012年(48)

2011年(65)

2010年(84)

2009年(121)

2008年(101)

2007年(129)

2006年(95)

2005年(118)

2004年(69)

分类: Oracle

2013-01-02 17:33:28


From: http://space.itpub.net/17203031/viewspace-695840


下午,一个开发组长过来找到笔者,说一个表被锁定,不能修改数据。开始以为是简单的,开发阶段由于工具使用的原因,经常发生锁表的事件。查找锁定对象,定位锁定人和机器之后,就可以了。

 

1、问题现象

 

但是实际情况,完全出乎笔者的想法。检查一般对象数据表锁定,只需要检查v$locked_objectv$transaction视图,就可以定位到具体人。但是检查之后的结果如下:

 

 

SQL> select * from v$locked_object;

   XIDUSN   XIDSLOT    XIDSQN OBJECT_ID SESSION_ID

---------- ---------- ---------- ---------- ----------

 

SQL> select * from v$transaction;

ADDR                XIDUSN   XIDSLOT    XIDSQN  

---------------- ---------- ---------- ----------

 

 

 

两个关键视图中,没有锁定的对象,也没有正在进行没有提交的事务。那是不是没有锁定呢?尝试对数据表加锁。

 

 

SQL> select * from nbs_common.inc_inputlog for update;

select * from nbs_common.inc_inputlog for update

 

ORA-01591:锁被未决处理4.30.31555持有

 

SQL> select count(*) from nbs_common.inc_inputlog;

 COUNT(*)

----------

      426

 

 

 

系统没有像一般阻塞那样等待,而是报错Ora-01591。并且提示锁被一个分布式事务持有,不能实现加锁操作。

 

看来是一个没有见到过的新错误。

 

2、分析问题

 

Ora-01591错误究竟是什么呢?我们使用oerr工具查看该错误编号,看看有没有值得关注的信息。

 

 

[oracle@bspdev ~]$ oerr ora 01591

01591, 00000, "lock held by in-doubt distributed transaction %s"

// *Cause: Trying to access resource that is locked by a dead two-phase commit

//         transaction that is in prepared state.

// *Action: DBA should query the pending_trans$ and related tables, and attempt

//         to repair network connection(s) to coordinator and commit point.

//         If timely repair is not possible, DBA should contact DBA at commit

//         point if known or end user for correct outcome, or use heuristic

//         default if given to issue a heuristic commit or abort command to

//         finalize the local portion of the distributed transaction.

 

 

 

简单的说,01591错误的原因是该对象被一个处在“in-doubt”状态的分布式事务锁定。分布式事务使用的是“two-phase commit”二阶段提交。解决该问题的方法就是查看内部表pending_trans$,确定分布式事务信息。这种状态的事务主要是由于在进行分布式事务时候,发生网络突发中断的情况,引起分布式事务无法正常结束,等待中断节点的事务响应。于是,各节点的事务所锁定的表就不会被释放掉。

 

 

此时,我们检查视图DBA_2PC_PENDING(或者基表pending_trans$),查看是否存在这种情况。

 

 

SQL> select * from DBA_2PC_PENDING;

 

LOCAL_TRAN_ID   GLOBAL_TRAN_ID                      STATE           

---------------------- ----------------------------------------------------- ----------------

4.30.31555  096044365.31302E312E33392E38392E746D30303034313030303237  Pepared

 

(篇幅原因,有省略……

 

果然,当前存在一个阻塞分布式事务,处在prepared状态。

 

3、知识介绍

 

现代数据库系统往往伴随着复杂的结构和环境,其中分布式数据库组成是一个重要方面。系统后台的数据库系统不再是由单个数据构成,而是由多***立数据库、甚至是多台异构数据库构成。这种情况下,分布式事务就是开发设计人员不能不面对的一个难题。

 

处理分布式事务的方案,有两种趋势。其一是借助数据库自身的分布式处理能力,如的分布式二阶段提交模型,进行多个数据库的分布式事务同步。其二是将分布式事务处理权交付给应用中间层,让应用去处理分布式事务问题。

 

 

进行分布式事务的时候,使用的“二阶段提交”模型,大致分为几个过程。(参考:http://blog.itpub.net/post/38439/477038

 

ü        Prepare阶段:多个数据库的commit_point_strength进行比较,确定出一个数据库作为commit point site。由全局协调者(Global Coordinator)通知除了commit point site外所有节点准备好commitrollback。同时,各节点对事务相关数据表加锁。之后,各个节点通知全局协调者自己的SCN,选择最大的那个SCN作为当前事务的SCN注意,从此刻开始,除了commit point site外,其他节点均进入in_double状态;

ü        Commit阶段:全局协调者将确定好的最大SCN通知给commit point site,授权该节点进行commit操作。Commit point site进行事务commit/rollback之后,通知全局协调者事务完成。全局协调者通知其他所有节点进行commit操作;

ü        Forget阶段:当各个节点结束事务之后,通知commit point site当前事务已经完成。当全部都完成了,commit point site开始清理分布式事务信息,然后通知全局协调者清理信息。最后全局协调者将最后清理掉本地的事务信息;

 

 

当前问题,主要是源于在进入prepared阶段之后,发生了网络中断的现象,引起commit的阶段不能等待到事务信息。所以,才会一直处在Prepared状态,数据表也就不会进行释放。

 

4、问题解决

 

对于这个事务,只能通过连接网络或者强制提交回退事务来结束。我们可以使用commit force或者rollback force来进行处理。

 

 

SQL> rollback force '4.30.31555';

 

Rollback complete

 

 

Rollback force参数是DBA_2PC_PENDING中记录本地事务信息的编号。

 

此时,再次查看数据。

 

 

SQL> select * from DBA_2PC_PENDING;

 

LOCAL_TRAN_ID   GLOBAL_TRAN_ID                          STATE  

---------------------- ----------------------------------------------------------

4.30.31555 096044365.31302E312E33392E38392E746D30303034313030303237forced rollback   

 

 

此时,该事务状态已经变化为forced rollback。已经强制回退。

 

 

SQL> select seq_number from nbs_common.inc_inputlog where rownum<2 for update;

 

   SEQ_NUMBER

--------------

            2

 

 

 

5、结论

 

这个故障解决,使我获取到如下认识:

 

ü        系统一旦涉及到分布式数据库,整体的复杂性就要提升很多。所以,要对分布式事务处理技术有非常成熟的认识和理解,而且要经过严格的测试;

ü        锁表的现象多种,不同事务类型,查看信息的方式有所差异;

阅读(2387) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~