oracle - 仅通过一个事件 session 随机获得ORA-08177

标签 oracle odp.net ora-08177

我正在运行一个程序,该程序创建一个表,然后插入一些数据。
这是唯一访问数据库的程序。
我随机得到ORA-08177。
实际的代码有些复杂,但是我编写了一个简单的程序来再现这种行为。

using System;
using System.Data;
using Oracle.DataAccess.Client;

namespace orabug
{
  class Program
  {
    private const string ConnectionString = ""; // Valid connection string here

    // Recreates the table
    private static void Recreate()
    {
      using (var connection = new OracleConnection(ConnectionString)) {
        connection.Open();
        using (var command = connection.CreateCommand()) {
          command.CommandText = @"
            declare
              table_count binary_integer;
            begin
              select count(*) into table_count from sys.user_tables where table_name = 'TESTTABLE';
              if table_count > 0 then
                execute immediate 'drop table TestTable purge';
              end if;
              execute immediate 'create table TestTable(id nvarchar2(32) primary key)';
            end;";
          command.ExecuteNonQuery();
        }
        connection.Close();
      }
    }

    // Opens session sessionCount times, inserts insertCount rows in each session.
    private static void Insert(int sessionCount, int insertCount)
    {
      for (int sessionNumber = 0; sessionNumber < sessionCount; sessionNumber++)
        using (var connection = new OracleConnection(ConnectionString)) {
          connection.Open();
          using (var transaction = connection.BeginTransaction(IsolationLevel.Serializable)) {
            for (int insertNumber = 0; insertNumber < insertCount; insertNumber++)
              using (var command = connection.CreateCommand()) {
                command.BindByName = true;
                command.CommandText = "insert into TestTable (id) values(:id)";
                var id = Guid.NewGuid().ToString("N");
                var parameter = new OracleParameter("id", OracleDbType.NVarchar2) {Value = id};
                command.Parameters.Add(parameter);
                command.Transaction = transaction;
                command.ExecuteNonQuery();
              }
            transaction.Commit();
          }
          connection.Close();
        }
    }

    static void Main(string[] args)
    {
      int iteration = 0;
      while (true) {
        Console.WriteLine("Running iteration: {0}", iteration);
        try {
          Recreate();
          Insert(10, 100);
          Console.WriteLine("No error");
        }
        catch (Exception exception) {
          Console.WriteLine(exception.Message);
        }
        iteration++;
      }
    }
  }
}

此代码无限循环运行。
在每次迭代中,它将执行以下10次操作:
  • 打开 session
  • 插入100行随机数据
  • 关闭 session
  • 显示一条消息,指出没有发生错误

  • 如果发生错误,则捕获异常并打印其消息,然后
    然后执行下一个迭代。

    这是示例输出。如您所见,ORA-08177随机交织成功的交际。
    Running iteration: 1
    No error
    Running iteration: 2
    ORA-08177: can't serialize access for this transaction
    Running iteration: 3
    ORA-08177: can't serialize access for this transaction
    Running iteration: 4
    ORA-08177: can't serialize access for this transaction
    Running iteration: 5
    ORA-08177: can't serialize access for this transaction
    Running iteration: 6
    ORA-08177: can't serialize access for this transaction
    Running iteration: 7
    No error
    Running iteration: 8
    No error
    Running iteration: 9
    ORA-08177: can't serialize access for this transaction
    Running iteration: 10
    ORA-08177: can't serialize access for this transaction
    Running iteration: 11
    ORA-08177: can't serialize access for this transaction
    Running iteration: 12
    ORA-08177: can't serialize access for this transaction
    Running iteration: 13
    ORA-08177: can't serialize access for this transaction
    Running iteration: 14
    ORA-08177: can't serialize access for this transaction
    Running iteration: 15
    ORA-08177: can't serialize access for this transaction
    Running iteration: 16
    ORA-08177: can't serialize access for this transaction
    Running iteration: 17
    No error
    Running iteration: 18
    No error
    Running iteration: 19
    ORA-08177: can't serialize access for this transaction
    Running iteration: 20
    No error
    

    我正在运行Oracle 11.1.0.6.0并使用ODP.NET 2.111.6.20。
    将隔离级别更改为ReadCommited可以解决此问题,但是我真的想在Serializable级别上运行此操作。
    看起来像I'm not alone
    这个问题,但没有给出答案,所以我再次询问。
    我在做什么错,我该如何解决?

    由APC编辑

    为防止其他人吠叫错误的树,发布的代码示例只是ORA-8177错误的生成器。显然,实际的代码是不同的。具体地说,删除和重新创建表是一个红色的鲱 fish 。

    最佳答案

    完全重写(第一次绕错了树)。

    SERIALIZABLE隔离级别在“感兴趣的交易”列表中占据一个位置。如果Oracle无法获得插槽,则它将发出ORA-8177。可用的ITL插槽数由INITRANS和MAXTRANS控制。根据the documentation:

    To use serializable mode, INITRANS must be set to at least 3.



    必须为表及其索引都设置此选项。那么,您的INITRANS设置是什么?当然,您的示例代码使用默认值(表1,索引2)。

    关于oracle - 仅通过一个事件 session 随机获得ORA-08177,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2326750/

    相关文章:

    Oracle.DataAccess不匹配错误

    oracle - ORA-08177: 无法序列化此事务的访问

    java - 如何在 Linux 上使用 Java 程序导出路径?

    c# - SQL Server 相当于 Oracle 'table of integer'

    sql - 甲骨文11g : query performance optimization

    oracle - 用于创建物化 View 的表空间?

    c# - 如何在 EF 6 提供程序配置文件中添加/激活 "Oracle.ManagedDataAccess.Client"?

    oracle - 在 Entity Framework/ODP.NET 中的数据库读/写事件之前设置 Oracle session 变量