微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

oracle – 随机获取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次:

>打开会话
>使用随机数据插入100行
>关闭会话
>显示一条消息,表示没有发生错误

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

这里是示例输出。正如你所看到的那样,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错误生成器。显然实际代码是不同的;具体来说,丢弃和重建桌子是一个红色的鲱鱼。

总重写(第一次出现错误的树)。

SERIALIZABLE隔离级别在“感兴趣的事务列表”中抓取一个插槽。如果Oracle无法获得一个插槽,那么它会引发ORA-8177。可用的ITL插槽的数量由INITRANS和MAXTRANS控制。根据the documentation

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

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

原文地址:https://www.jb51.cc/oracle/206073.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐