Eccezione di timeout anche dopo aver impostato la proprietà di timeout per l'operazione

ado.net c# sqlbulkcopy sql-server timeoutexception

Domanda

Problema di timeout:

Timeout scaduto. Il periodo di timeout è trascorso prima del completamento dell'operazione o il server non risponde. \ R \ nLa dichiarazione è stata chiusa.

Ho 17 milioni di record da scaricare nel database dell'applicazione. Questi 12 milioni di record sono il risultato di un'operazione di confronto tra 2 record di database.

Confronto tra due record di database, quindi compilo i record non corrispondenti (sulla base di alcuni criteri) nella tabella dati e una volta che la tabella dati raggiunge un limite come 1000 o 500 ecc. Invio questa tabella dati alla copia bulk SQL per l'importazione bulk e quindi svuota la tabella dati .

Sto facendo tutta questa operazione all'interno della transazione in modo che ho inserito i record X e durante il mio processo di comparazione non arriva nessun errore, quindi eseguirò il rollback di quei record X.

Ma a causa di questo, sto ottenendo un problema di timeout che fa poi copia bulk.

Ho controllato diversi batchsize like 5000,1000,500,300 diversi batchsize like 5000,1000,500,300 ecc. Sto riscontrando problemi di timeout in tutte le dimensioni di questo batch.

Una volta impostato il timeout della copia bulk su 0 ma poi si passa a questo errore di seguito:

Il log delle transazioni per il mio database è pieno.

Con 1000 record raggiunge 2,7 milioni e poi genera problemi di timeout,

Con 500 record ha raggiunto circa 2,1 milioni di record quindi genera un errore.

Con 300,200,100 lancia anche errori di timeout.

Ho anche impostato il timeout della connessione nella mia stringa di connessione a 30 minuti.

Codice :

public class SaveRepo : IDisposable
    {
        DataTable dataTable;
        SqlConnection connection;
        string connectionString;
        SqlTransaction transaction;
        SqlBulkCopy bulkCopy;
        int testId,

        public SaveRepo (int testId)//testId=10364
        {
            this.connectionString = connectionString;
            dataTable = new DataTable();
            connection = new SqlConnection(connectionString);
            connection.Open();
            transaction = connection.BeginTransaction();
            bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction);
            bulkCopy.BulkCopyTimeout = 60;
            bulkCopy.EnableStreaming = true;
            bulkCopy.DestinationTableName = "dbo.Sales";
            bulkCopy.BatchSize = 100;
            bulkCopy.SqlRowsCopied +=
                  new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
            bulkCopy.NotifyAfter = 100;
        }

       void Dump()
        {
            try
            {
                bulkCopy.WriteToServer(dataTable);
            }
            catch(Exception ex) // timeout error
            {
                throw ex;
            }
        }

    void FillDatatable(object[] row)
    {
        if (dataTable.Rows.Count == 100)
        {
           Dump();
           dataTable.Clear();
        }
        dataTable.Rows.Add(row);
    }

        public void End()
        {
            transaction.Commit();
            //dispose the stuffs also
        }
    }

C'è qualche altro modo o soluzione che mi manca e in grado di risolvere questo problema di timeout?

Aggiornamento: dopo aver impostato BulkCopyTimeout su 0 e con batchsize =1000 ho ricevuto questo errore fino a 3593000 records bulk copied :

Impossibile allocare spazio per l'oggetto "dbo.Sales". "PK_dbo.Sales" nel database "XYZ" perché il filegroup "PRIMARY" è pieno. Crea spazio su disco eliminando i file non necessari, rilasciando oggetti nel filegroup, aggiungendo altri file al filegroup o impostando la crescita automatica per i file esistenti nel filegroup.

Aggiornamento 2: ho rimosso la transazione e aprirò e chiuderò la connessione per ogni lotto e, mentre scarico qualsiasi lotto se si verifica un errore, rimuoverò tutti i dati precedentemente salvati usando testId . Ora funziona scaricando 3 millions of data ottengo questo errore:

Impossibile allocare spazio per l'oggetto "dbo.Sales". "PK_dbo.Sales" nel database "XYZ" perché il filegroup "PRIMARY" è pieno. Crea spazio su disco eliminando i file non necessari, rilasciando oggetti nel filegroup, aggiungendo altri file al filegroup o impostando la crescita automatica per i file esistenti nel filegroup.

Questo va nella sezione catch in cui cerco di rimuovere vecchi dati basati su testId ma ci vuole così tanto tempo e poi genera questo errore:

Il log delle transazioni per il mio database è pieno.

void Dump()
        {
            using (SqlConnection connection =
                  new SqlConnection(connectionString))
            {
                connection.Open();
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
                {
                    bulkCopy.DestinationTableName = "dbo.Sales";
                    bulkCopy.EnableStreaming = true;
                    try
                    {
                        bulkCopy.WriteToServer(dataTable);
                    }
                    catch(Exception ex)
                    {
                        connection.Close();
                        SalesRepo.Delete(connectionString, testId);
                    }
                }
            }
        }

Risposta popolare

Quindi nella tua seconda opzione sei stato in grado di "scaricare" i dati nell'uso del codice nel database solo per scoprire che stai esaurendo la dimensione del file sul database.

Questo può accadere quando la crescita automatica è impostata su cadute e o hai raggiunto la dimensione massima del file disponibile sul disco.

Il tuo primo tentativo non è riuscito in quanto la transazione è diventata grande per mantenere l'utilizzo delle risorse del server.

Prime 2 cose:

  1. Eseguire il backup del registro delle transazioni se il database è in modalità di ripristino completo o "verificare" il database per accertarsi di avere lo spazio di registrazione.
  2. Striscia la tua tabella su più file, fai questo creando un gruppo di file che contiene diversi file, il migliore è di distribuirli su più array / controller del disco in modo da poter confrontare le scritture

Poi,

  • Dovrai ricreare gli indici come gli indici sono stati disabilitati dopo tale errore.
  • le statistiche dei dati saranno davvero pessime dopo un così grande aggiornamento
  • ogni indice rallenterà l'inserimento di un fattore, se gli indici sono cattivi questo rallenterà davvero le cose a seconda di quante divisioni di indice si ottengono (se i dati vengono inseriti nell'ordine morbido dell'indice o contro di esso, se contro di esso è come impilare casse di birra dal basso invece che in alto se capisci cosa intendo.
  • se si dispone di una versione Enterprise utilizzata una funzione di partizione, ciò velocizzerà notevolmente l'azione poiché è possibile elaborare in modo parallelo i dati e ridurre il blocco ai dati partizionati.

Prova a fare il backup nel mezzo della tua "importazione", in quanto il backup manterrà i dati che sono stati commessi transnazionali e il tuo file LDF sarà meno stressato.

Spero di aver aiutato

Walter



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow