Oracle:在我们的测试中截断表时,有时会出现死锁

Oracle:在我们的测试中截断表时,有时会出现死锁,oracle,deadlock,Oracle,Deadlock,我们每天晚上在Oracle数据库上运行大约500个测试 在每次测试之前,我们使用以下代码截断所有表: public override void EmptyTables() { const string alterConstraints = "begin for i in (select c.* from user_constraints c, user_tables u where c.table_name = u.table_name and c.constra

我们每天晚上在Oracle数据库上运行大约500个测试

在每次测试之前,我们使用以下代码截断所有表:

    public override void EmptyTables()
    {
        const string alterConstraints = "begin for i in (select c.* from user_constraints c, user_tables u where c.table_name = u.table_name and c.constraint_type = 'R') LOOP EXECUTE IMMEDIATE 'alter table ' || i.table_name || ' {0} constraint ' || i.constraint_name; end loop; end;";

        List<string> commandList = new List<string>();
        commandList.Add( string.Format( alterConstraints, "disable" ) );
        commandList.AddRange( GetTableNames().Select( tn => string.Format( "truncate table {0}", tn ) ) );
        commandList.Add( string.Format( alterConstraints, "enable" ) );

        ExecuteNonQuery( commandList );
    }

    public virtual void ExecuteNonQuery( IList<string> statements )
    {
        DbTransaction dbTransaction = DbConnection.BeginTransaction();
        foreach( string statement in statements )
        {
            DbCommand dbComand = CreateDbCommand( statement, dbTransaction );
            dbComand.CommandTimeout = 60 * 30;

            try
            {
                dbComand.ExecuteNonQuery();
            }
            catch( Exception exception )
            {
                HandleExecuteNonQueryException( exception, dbTransaction, statement );
            }
            finally
            {
                dbComand.Dispose();
            }
        }

        dbTransaction.Commit();
    }
几乎每晚都会有5个随机测试在ExecuteOnQuery中失败,使用ORA-00060或ORA-04020死锁语句:alter table SOMETABLE disable constraint FK_SOMEFK=>表和FK以及disable/enable也是随机的

我知道找出问题可能非常棘手,但有没有人能想到:


谢谢

我将从收集关于测试失败的静态信息开始

每次调用EmptyTables方法之前,请检查并记录查询结果:

select obj.owner,
       obj.object_name,
       obj.object_type,
       s.sid,
       s.serial#,
       s.status,
       s.osuser,
       s.machine
  from v$locked_object lo,
       v$session s,
       dba_objects obj
 where s.sid = lo.session_id
   and lo.object_id = obj.object_id;
首先,查找在以前的测试运行中打开的会话锁定的对象

С考虑到故障的随机性和情况的可重复性,我发现两种可疑的可能性:

如果您使用多个会话运行测试,由于某些原因,上一个测试的会话没有足够的时间释放资源。这是您第一次可以终止查询找到的会话,直到您理解它们没有被正确关闭的原因

如果所有测试都重用同一个会话,正如在测试运行时其他人使用模式的注释中提到的那样。但我认为情况并非如此,因为您只为测试运行创建了良好的隔离模式:我希望您在开始测试之前创建它,并在测试之后删除它

要快速失败,您可以在DDL操作之前锁定每个表:

LOCK TABLE table_name IN EXCLUSIVE MODE NOWAIT;

最明显的是,有人在用这张桌子。在更改表之前,请尝试更改会话设置DDL_LOCK_TIMEOUT=60,这会给您最多60秒的等待时间。谢谢,我会尝试让您知道。不,没有帮助。谢谢,我会尝试让您知道。目前没有表v$session的权限。