Je cours un programme qui crée une table et insère ensuite des données.
Ceci est le seul programme qui accède à la base de données.
Je reçois ORA-08177 au hasard.
Le code réel est quelque peu complexe, mais j'ai écrit un programme simple qui reproduit ce comportement.Obtenir aléatoirement ORA-08177 avec une seule session active
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++;
}
}
}
}
Ce code exécute un cycle infini.
A chaque itération, il effectue les actions suivantes 10 fois:
séance ouverte
Insérer 100 lignes avec des données aléatoires
session Fermer
Affiche un message indiquant que aucune erreur n'est survenue
Si une erreur se produit, l'exception est interceptée et son message est imprimé et , puis l'itération suivante est exécutée.
Voici un exemple de sortie. Comme vous pouvez le voir ORA-08177 est entrelacé avec des interations réussies au hasard.
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
Je cours Oracle 11.1.0.6.0 et en utilisant ODP.NET 2.111.6.20.
La modification du niveau d'isolation à ReadCommited
résout le problème, mais je veux vraiment l'exécuter au niveau Serializable
.
On dirait I'm not alone avec ce problème, mais la réponse n'a pas été donnée, alors je demande à nouveau.
Qu'est-ce que je fais de mal et comment pourrais-je résoudre ce problème?
modifier par APC
Pour empêcher quiconque d'aboyer autre le mauvais arbre, l'exemple de code affiché est juste un générateur d'erreurs ORA-8177. Apparemment, le code réel est différent. plus précisément, l'abandon et la recréation de tableaux est un faux-fuyant.
C'est juste un exemple de programme qui démontre ce comportement étrange. L'application réelle ne supprime pas les tables à chaque démarrage. Mais la suite de tests pour cette application réelle recrée toutes les tables et télécharge ensuite les données de test. À ce moment-là, je suis confronté à ce problème. –
@Denis: Ensuite, laissez les tables à cet endroit, et récupérez les erreurs "table existe déjà" dans le code. –
De telles solutions de contournement ne sont pas ce que prévu ici. Il est nécessaire de connaître la cause réelle. // Je suis également conscient de la question –