暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

【技术文章】ORA-02049分布式事务锁原因分析以及处理方法

云贝教育 2022-10-19
8265

现象:

报错ORA-02049: timeout: distributed transaction waiting for lock


1.原因

1.1 存在DB-LINK(以appl.test@db1 举例,任意一个DBLINK都可以)

1.2 申请TX锁发生阻塞(以cux_test_1举例,当然任意一个表都可以)

1.3 阻塞时间超过 show parameter DISTRIBUTED_LOCK_TIMEOUT 设置的时间,默认是60秒


2.重现

2.1 先在窗口1,执行
    select * from cux_test_1 for update ;
    2.2 然后在窗口2,依次执行
      select  * from appl.test@db1 where rownum<=21;
      为什么是21,因为rownum=1未产生事务,初步怀疑是从buffer cache获取的,没有经过DBLINK
        select * from cux_test_1 for update ;
        2.3 等待60秒,出现报错


        3.解决

        窗口2加一个commit,用于结束DBLINK产生的事务
          select  * from appl.test@db1 where rownum<=21;
          commit;--只需要在访问DBLINK之后,加这一行,就可以了
            select * from cux_test_1 for update ;


            4.名词解释

            什么是分布式事务?
            分布式事务包括一个或多个语句,这些语句单独或作为一组更新分布式数据库的两个或多个不同节点上的数据

            参考链接:Managing Distributed Transactions (oracle.com)

            4.1 执行查询dblink,然后同一窗口查询事务表
              select  * from appl.test@db1
              4.2 可以看出来确实产生了一笔事务,但是插槽号确实为空,表示未更新块头信息。同时文件号和块号都是为空,表示空事务
                SELECT t.xidusn, --回滚段号
                t.xidslot, --插槽号
                t.xidsqn, --序列号
                t.ubafil, --undo 文件号
                t.ubablk, --undo 块号
                (SELECT DISTINCT tablespace_name
                FROM dba_undo_extents e
                WHERE e.file_id = t.ubafil) tablespace_name,--查询undo 段信息


                (SELECT tablespace_name
                FROM dba_data_files e
                WHERE e.file_id = t.ubafil) tablespace_name --数据文件表执行的表空间
                FROM gv$transaction t, gv$session s
                WHERE t.ses_addr = s.saddr
                AND s.sid = userenv('sid')
                 所以执行查询DBLINK等价于 savepoint
                 但是savepoint 不是分布式的,所以不会报错。
                 关于查询dbLink产生事务的原因:
                /* 数据库必须保证事务中的所有语句(分布式的或非分布式的)作为一个单元提交或回滚。正在进行的事务的影响应该对所有节点上的所有其他事务是不可见的;对于包含任何类型的操作(包括查询、更新或远程过程调用)的事务,这种透明度应该是真实的。
                在Oracle数据库概念中讨论了非分布式数据库中事务控制的一般机制。在分布式数据库中,即使发生网络或系统故障,数据库也必须在网络上协调具有相同特征的事务控制,并保持数据的一致性。
                数据库两阶段提交机制保证参与分布式事务的所有数据库服务器全部提交或全部回滚事务中的语句。两阶段提交机制还保护由完整性约束、远程过程调用和触发器执行的隐式DML操作。

                */

                查询分布式事务
                  select  * from gv$global_transaction;
                  如果有结果表示当前会话存在分布式锁
                    select * from gv$lock where sid=userenv('sid') AND TYPE='DX'
                    用完如果不会再次访问此DBLINK,可以强制断开DBLINK链接
                      BEGIN
                      COMMIT;--释放dblink占用
                      dbms_session.close_database_link('db1');--关闭远程连接,等价于commit;alter session close database link db1;




                      COMMIT;--结束事务,即使没有写任何DML语句
                      END;


                      文章转载自云贝教育,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论