Exception de délai d'attente même après avoir défini la propriété de délai d'attente pour l'opération

ado.net c# sqlbulkcopy sql-server timeoutexception

Question

Problème de délai d'attente:

Le délai d'attente a expiré. La période de temporisation s'est écoulée avant la fin de l'opération ou le serveur ne répond pas. \ R \ nL'instruction est terminée.

J'ai 17 millions d'enregistrements à vider dans ma base de données d'applications. Ces 12 millions d'enregistrements sont le résultat d'une opération de comparaison entre 2 enregistrements de base de données.

Je compare 2 enregistrements de base de données, puis je renseigne les enregistrements incompatibles (en fonction de certains critères) dans la table de données et une fois que la table de données atteint une limite telle que 1000 ou 500, etc. .

Je suis en train de faire toute cette opération dans la transaction, de sorte que j'ai inséré des enregistrements X. Lors de mon processus de comparaison, toute erreur survient. Je vais donc restaurer ces enregistrements X.

Mais à cause de cela, je reçois un problème de délai d’attente qui s’effectue alors en bloc.

J'ai vérifié différentes batchsize like 5000,1000,500,300 exemple batchsize like 5000,1000,500,300 etc. Je reçois des problèmes de dépassement de délai d'attente pour toute la taille de ce lot.

Une fois que j'ai défini le délai d'expiration de la copie en bloc sur 0, je commets ensuite l'erreur ci-dessous:

Le journal des transactions pour ma base de données est plein.

Avec 1000 enregistrements, il atteint 2,7 millions et pose ensuite des problèmes de dépassement de délai,

Avec 500 enregistrements, il a atteint 2,1 millions d’enregistrements, puis une erreur est générée.

Avec 300 200 100, il génère également des erreurs de dépassement de délai.

J'ai également défini le délai de connexion dans ma chaîne de connexion à 30 minutes.

Code:

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
        }
    }

Existe-t-il un autre moyen ou une solution qui me manque et qui puisse résoudre ce problème de délai d'attente?

Mise à jour: Après avoir défini BulkCopyTimeout sur 0 et que batchsize =1000 cette erreur s'est 3593000 records bulk copied jusqu'à ce que 3593000 records bulk copied :

Impossible d'allouer de l'espace pour l'objet 'dbo.Sales'. 'PK_dbo.Sales' dans la base de données 'XYZ' car le groupe de fichiers 'PRIMARY' est saturé. Créez de l'espace disque en supprimant des fichiers inutiles, en déposant des objets dans le groupe de fichiers, en ajoutant des fichiers supplémentaires au groupe de fichiers ou en définissant la croissance automatique des fichiers existants dans le groupe de fichiers.

Mise à jour 2: J'ai supprimé la transaction et je vais ouvrir et fermer la connexion pour chacun des lots et lors du vidage d'un lot en cas d'erreur, je supprime toutes les données précédemment sauvegardées à l'aide de testId Maintenant, cela fonctionne jusqu'à ce que 3 millions of data testId vidées. je reçois cette erreur:

Impossible d'allouer de l'espace pour l'objet 'dbo.Sales'. 'PK_dbo.Sales' dans la base de données 'XYZ' car le groupe de fichiers 'PRIMARY' est saturé. Créez de l'espace disque en supprimant des fichiers inutiles, en déposant des objets dans le groupe de fichiers, en ajoutant des fichiers supplémentaires au groupe de fichiers ou en définissant la croissance automatique des fichiers existants dans le groupe de fichiers.

Cela va dans la section catch où j'essaie de supprimer les anciennes données basées sur testId mais cela prend tellement de temps et ensuite cela jette cette erreur:

Le journal des transactions pour ma base de données est plein.

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);
                    }
                }
            }
        }

Réponse populaire

Donc, sur votre deuxième option, vous avez réellement été en mesure de "vider" les données de l’utilisation du code dans la base de données uniquement pour découvrir que vous manquez de la taille du fichier dans la base de données.

Cela peut se produire lorsque la croissance automatique est définie sur une chute et que vous avez atteint la taille de fichier maximale disponible sur votre disque.

Votre première tentative a échoué lorsque la transaction est devenue trop lourde à gérer en utilisant les ressources de votre serveur.

2 premières choses:

  1. Sauvegardez votre journal des transactions si votre base de données est en mode de récupération complète ou "vérifiez" la base de données pour vous assurer que vous disposez de l'espace de journalisation.
  2. Répartissez votre tableau sur plusieurs fichiers. Pour ce faire, vous créez un groupe de fichiers contenant plusieurs fichiers. Le mieux est de les répartir sur plusieurs matrices de disques / contrôleurs afin de pouvoir mettre en parallèle les écritures.

Alors,

  • Vous devrez recréer les index car ceux-ci ont été désactivés après une telle erreur.
  • les statistiques de données vont être vraiment mauvais après une telle mise à jour
  • chaque index ralentira l'insertion d'un facteur. Si les index sont mauvais, cela ralentira vraiment les choses en fonction du nombre de fractionnements d'index que vous obtenez (si vos données sont insérées dans l'ordre progressif de l'index par contre, cela revient à empiler des caisses de bière par le bas au lieu d’en haut si vous comprenez ce que je veux dire.
  • Si vous avez une version Enterprise qui utilise une fonction de partition, cela accélérera considérablement l'action car vous pouvez réellement traiter les données en parallèle et réduire le verrouillage sur les données partitionnées.

Essayez de sauvegarder au milieu de votre "importation" car la sauvegarde persistera les données transnationales et votre fichier LDF sera moins stressé.

J'espère avoir aidé

Walter



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi