我正在运行一个创建一个表然后插入一些数据的程序。
这是访问数据库的唯一程序。
我随机得到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错误的生成器。显然实际代码是不同的;具体来说,丢弃和重建桌子是一个红色的鲱鱼。
总重写(第一次出现错误的树)。
原文链接:https://www.f2er.com/oracle/206073.htmlSERIALIZABLE隔离级别在“感兴趣的事务列表”中抓取一个插槽。如果Oracle无法获得一个插槽,那么它会引发ORA-8177。可用的ITL插槽的数量由INITRANS和MAXTRANS控制。根据the documentation:
To use serializable mode,INITRANS
must be set to at least 3.
必须为表及其索引设置此值。那么你的INITRANS设置是什么?当然,您的示例代码使用默认值(表为1,索引为2)。