Oracle:在我们的测试中截断表时,有时会出现死锁
我们每天晚上在Oracle数据库上运行大约500个测试 在每次测试之前,我们使用以下代码截断所有表: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
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的权限。