Zufälliges Abrufen von ORA-08177 mit nur einer aktiven Sitzung
Ich führe ein Programm aus, das eine Tabelle erstellt und dann einige Daten einfügt.
Dies ist das einzige Programm, das auf die Datenbank zugreift.
Ich bekomme zufällig ORA-08177.
Tatsächlicher Code ist etwas komplex, aber ich habe ein einfaches Programm geschrieben, das dieses Verhalten reproduziert.
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++;
}
}
}
}
Dieser Code läuft im unendlichen Zyklus.
Bei jeder Iteration werden zehnmal die folgenden Aktionen ausgeführt:
Sitzung eröffnen
Fügen Sie 100 Zeilen mit zufälligen Daten ein
Sitzung schließen
Zeigt eine Meldung an, dass kein Fehler aufgetreten ist
Wenn ein Fehler auftritt, wird die Ausnahmebedingung abgefangen und ihre Nachricht gedruckt. Anschließend wird die nächste Iteration ausgeführt.
Hier ist eine Beispielausgabe. Wie Sie sehen, verschachtelt sich ORA-08177 zufällig mit erfolgreichen Interaktionen.
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
Ich verwende Oracle 11.1.0.6.0 und ODP.NET 2.111.6.20.
Ändern der Isolationsstufe aufReadCommited
behebt das Problem, aber ich möchte dies unbedingt ausführenSerializable
Niveau.
Sieht aus wieich bin nicht alleine mit diesem problem wurde aber keine antwort gegeben, also frage ich nochmal.
Was mache ich falsch und wie kann ich das beheben?
bearbeitet von APC
Um zu verhindern, dass andere den falschen Baum anschlagen, ist das Beispiel für den veröffentlichten Code nur ein Generator für ORA-8177-Fehler. Anscheinend ist der tatsächliche Code anders; Insbesondere das Ablegen und Wiederherstellen von Tischen ist ein roter Hering.