L'applicazione stessa descritta nel mio precedente question. Sul lato DAL io usoODP .NET si comporta in modo strano
Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342
Ecco stringa di connessione:
User id=usr;Password=pwd;Data Source=database1;Validate connection=True;Connection timeout=8;Pooling=false
Lo starange è che a volte ODP solleva fuori seguente eccezione:
Oracle.ManagedDataAccess.Client.OracleException (0xFFFFFC18): Connection request timed out
in OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName)
in OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
in OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
in OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword)
in Oracle.ManagedDataAccess.Client.OracleConnection.Open()
in MySyncApp.DBRepository.GetChangedDataDB(DateTime startPeriod) in D:\MySyncApp\MySyncApp\DB.cs:line 23
in MySyncApp.Program.<>c__DisplayClass30.<>c__DisplayClass32.<Synchronize>b__2f(ID id) in D:\MySyncApp\MySyncApp\Program.cs:line 441
Ma dopo questa eccezione, quando ho guarda le sessioni in Oracle, vedo che la connessione è attualmente in vita e contrassegnata come INACTIVE
! Quindi, tali connessioni continueranno a rimanere sul lato server, esaurendo gradualmente il conteggio delle sessioni disponibili.
Non c'è niente di speciale nel mio codice, basta
public List<DataObj> GetChangedDataDB(DateTime startPeriod)
{
List<DataObj> list = new List<DataObj>();
using (OracleConnection conn = new OracleConnection(this._connstr))
{
conn.Open();
using (OracleCommand comm = new OracleCommand("select data from table(usr.syncpackage.GetChanged(:pStart))", conn))
{
comm.CommandTimeout = 10;
comm.Parameters.Add(":pStart", startPeriod);
using (OracleDataReader reader = comm.ExecuteReader())
{
// ..omitted
}
}
}
return list;
}
Questo codice viene eseguito in Parallel.ForEach
ciclo per tirare fuori i dati da un sacco di basi di dati simultaneamente. Possono anche esserci tre connessioni parallele allo stesso database (estrarre dati da diverse parti dello schema, ad esempio, da tre diversi dipartimenti di impresa).
L'Oracle è
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Produzione
Il processo di sincronizzazione si spara sul timer in intervalli di 10 secondi. Se c'è già runnning compito allora prossimo compito viene arrestato:
public static void Synchronize(object obj)
{
// ... omitted
log.Info("ITERATION_COMMON_START");
if (Program.State == "Running")
{
log.Info("ITERATION_COMMON_END_BY_EXISTING");
return;
}
lock (Program.StateLock)
{
Program.State = "Running";
}
Parallel.ForEach(Global.config.dbs, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (l) =>
{
Console.WriteLine("Started synchronization for {0}", l.key);
DBRepository db = new DBRepository(l.connectionString);
Parallel.ForEach(l.departments, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (department) =>
{
DateTime ChangesFromTS = GetPreviousIterationTS;
List<DataObj> cdata = db.GetChangedDataDB(ChangesFromTS);
// ... doing the work here
}
}
// Finishing work
GC.Collect();
lock (Program.StateLock)
{
Program.State = "";
}
}
Ecco timer per invocare periodicamente sincronizzare le attività:
Program.getModifiedDataTimer = new Timer(Program.Synchronize, null, (int)Global.config.syncModifiedInterval * 1000, (int)Global.config.syncModifiedInterval * 1000);
Global.config.syncModifiedInterval
è espresso in secondi
ODP si comporta allo stesso modo quando accendo il pooling. Ha creato più connessioni di quelle consentite dalla direttiva Max pool size
nelle stringhe di connessione con la stessa eccezione.
Per favore dimmi i tuoi pensieri e la tua esperienza su quella roba.
UPDATE
Ecco un pezzo di Oracle traccia quando viene sollevata un'eccezione:
(PUB) (ERR) OracleConnection.Open() (txnid=n/a) Oracle.ManagedDataAccess.Client.OracleException (0xFFFFFC18): Connection request timed out
in OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName)
in OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
in OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
in OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword)
in Oracle.ManagedDataAccess.Client.OracleConnection.Open()
UPDATE # 2
sembra che questo mostra le connessioni in alto b a causa della connessione ritardata, come la richiesta di stabilire una connessione oracle viene inviata ma la sua risposta viene ignorata. O i dati trasmessi a/da server sono corrotti mentre vanno a destinazione.
Connessioni continua a bloccarsi nell'elenco delle sessioni del server anche quando si spegne l'applicazione. Quando uccido una sessione, continua a rimanere in lista con l'etichetta "KILLED".
UPDATE # 3
Here è l'applicazione demo che rende stesso problema. Come ho detto in precedenza, appare su una cattiva connessione, è possibile simulare tale connessione utilizzando l'emulatore WANem. Here è lo stesso componente che utilizzo per la connettività del database. Spero per il tuo aiuto.
È possibile fornire un dump dell'applicazione quando si verifica? – Olivier
@Olivier Si prega di vedere il mio terzo aggiornamento di domande. Spero ti renda più facile riprodurre il problema. Ma sì, sicuramente, posso fare una discarica. – kseen
Sei mai riuscito a risolverlo? –