Je suis confronté à une situation qui est quelque peu difficile à résoudre. J'ai besoin d'aide pour comprendre ce qui se passe.
TL; DR: Chaque fois que le journal des transactions est plein dans SQL Server, il a besoin de pour arrêter la base de données entrer en mode de récupération et annuler les transactions incriminées? Est-ce toujours fait par conception ou cela ne se produit que lorsque quelque chose de mauvais se produit?
Le scénario:
L'une de nos bases de données de production utilisées de façon intensive, qui exécute plusieurs travaux ETL et des lots de tables de longue durée, est entrée en mode de récupération et est devenue inaccessible pendant un certain temps. Cela s'est produit trois fois cette semaine (ce serveur fonctionne depuis environ 2 ans et nous n'avons pas remarqué ce problème par le passé).
En examinant les journaux d'erreurs, ce qui s'est passé est clair: le journal des transactions est plein, la base de données doit annuler la transaction, l'échec de la restauration, l'arrêt de la base de données et démarre en mode de récupération.
Le DBA défend cela comme un comportement normal de SQL Server. Autrement dit, selon lui, chaque fois que le journal des transactions est plein et qu'une transaction doit restaurer la base de données va entrer en mode de récupération en raison du manque d'espace dans le journal. Après le rollback (qui ne peut se faire qu'en mode Recovery selon lui), la base de données redeviendra disponible.
Je n'ai trouvé aucune référence pour cette info. Je suis donc fortement en désaccord. J'apprécierais vraiment si quelqu'un me convaincait que je me trompe.
Mon point:
À ma connaissance, un SGBD est conçu pour gérer/exécuter les requêtes. S'il manque d'espace, la requête échouera. C'est aussi simple que cela. Et je ne parle pas de performance d'autre chose, mais uniquement de disponibilité.
Cela n'a aucun sens pour moi d'accepter qu'un SGBD a besoin par conception de s'arrêter pour annuler toute transaction. À ma connaissance, peu importe si j'exécute des tonnes de requêtes ou si les requêtes sont mal conçues. Les mauvaises requêtes devraient échouer et la vie continue. N'est-ce pas?
Je suppose que quelque chose d'autre fait échouer, et je dois suivre ce qui se passe.
Ma compréhension est-elle fausse ou est-ce vraiment ainsi que SQL Server est conçu pour fonctionner? En supposant que je ne me trompe pas, que puis-je faire d'autre pour suivre la source de ce problème?
Quelques informations supplémentaires
select @@version
: Microsoft SQL Server 2012 (SP1) - 11.0.3156.0 (X64) 4 mai 2015 18:48:09 Copyright (c) Microsoft Corporation Standard Edition (64 bits) sur Windows NT 6.2 (Build 9200:)Sauvegarde du journal (par ordre d'occurrence, les doublons ont été supprimés)
[02:58:37am ~ 04:47:42pm, 12 times]
Erreur: 845. Gravité: 17. État: 1. Expiration du délai lors de l'attente du verrou de type 3 pour la page (1: 8728760). ID de base de données 7. FlushCache: nettoyé 10460 bufs avec 6709 écritures en 77540 ms (évité 864 nouveaux bufs sales) pour db 7: 0 débit moyen: 1,05 Mo/sec. Saturation d'E/S: 107. commutateurs de contexte 391 dernière cible en attente: 4800. avgWriteLatency 0 FlushCache: nettoyé 95448 bufs avec 37560 écritures en 85820 ms (évité 60465 nouveaux bufs sales) pour db 7: 0 débit moyen: 8,69 Mo/sec. Saturation E/S: 17026. commutateurs de contexte 20713 dernière cible en attente: 446. avgWriteLatency 3.
[02:58:37am ~ 04:47:42pm, 13 times]
Un délai d'attente s'est produit lors de l'attente du verrouillage du tampon - type 3. bp 000000109B9E69C0. page 1: 73430228. stat 0x10b. ID de la base de données: 7. ID de l'unité d'allocation: 72057594304790528. tâche 0x00000008BC0850C8: 1. temps d'attente 300 secondes. drapeaux 0x100000001a. propriétaire de la tâche 0x0000000827B38188. Ne continue pas d'attendre.
[02:58:37am ~ 04:47:42pm, 12 times]
Erreur: 5901. Gravité: 16. État: 1. Une ou plusieurs unités de récupération appartenant à la base de données 'XXXXXXXXXX' n'ont pas réussi à générer un point de contrôle. Cela est généralement dû au manque de ressources système telles que le disque ou la mémoire ou, dans certains cas, à la corruption de la base de données. Examinez les entrées précédentes dans le journal des erreurs pour obtenir des informations plus détaillées sur cet échec.
[05:14:29pm ~ 05:14:53pm, 9 times]
Erreur: 9002. Gravité: 17. État: 4. Le journal des transactions de la base de données 'XXXXXXXXXX' est plein en raison de 'ACTIVE_TRANSACTION'.
[05:14:53pm, once]
Erreur: 3314. Gravité: 21. État: 3. La base de données XXXXXXXXXX a été arrêtée en raison de l'erreur 3314 dans la routine 'XdesRMReadWrite :: RollbackToLsn'. Le redémarrage des bases de données non instantanées sera tenté une fois toutes les connexions à la base de données interrompues.
[05:14:53pm ~ 05:14:53pm, 16 times]
Erreur: 3314. Gravité: 21. État: 3. Lors de l'annulation d'une opération consignée dans la base de données 'XXXXXXXXXX', une erreur s'est produite à l'ID d'enregistrement de journal (8064074: 20971: 110). En règle générale, l'échec spécifique est enregistré précédemment en tant qu'erreur dans le service Journal des événements Windows. Restaurez la base de données ou le fichier à partir d'une sauvegarde ou réparez la base de données.
[05:14:53pm ~ 05:14:53pm, 9 times]
Erreur: 9001. Gravité: 21. État: 5.Le journal de la base de données 'XXXXXXXXXX' n'est pas disponible. Vérifiez le journal des événements pour les messages d'erreur associés. Résolvez les erreurs et redémarrez la base de données.
[05:14:58, once]
Démarrage de la base de données 'XXXXXXXXXX'.
[05:15:02, once]
La récupération de la base de données 'XXXXXXXXXX' (7) est terminée à 0% (il reste environ 2931 secondes). Phase 1 de 3. Il s'agit uniquement d'un message informatif. Aucune action de l'utilisateur n'est requise....
[05:51:01pm, once]
6 transactions annulées dans la base de données "XXXXXXXXXX" (7: 0). Il s'agit d'un message d'information uniquement. Aucune action de l'utilisateur n'est requise.
[05:51:01pm, once]
La récupération écrit un point de contrôle dans la base de données 'XXXXXXXXXX' (7). Il s'agit d'un message d'information uniquement. Aucune action de l'utilisateur n'est requise.
[05:56:47pm, once]
Récupération terminée pour la base de données XXXXXXXXXX (ID de base de données 7) en 2505 seconde (s) analyse 1774 ms refaire 406623 ms undo 1749182 ms.) Il s'agit uniquement d'un message d'information. Aucune action de l'utilisateur n'est requise.
Je n'ai trouvé aucune autre entrée de journal pertinente dans le journal des erreurs ou l'Observateur d'événements. L'erreur la plus proche qui se produit dans l'Observateur d'événements est:
[04:56:45pm ~ 05:27:24pm, 13 times]
Les paramètres d'autorisation spécifiques à l'application n'accordent pas l'autorisation d'activation locale pour l'application COM Server avec CLSID {FDC3723D-1588-4BA3-92D4-42C430735D7D} et APPID {83B33982-693D-4824-B42E-7196AE61BB05} à l'utilisateur MY_DOMAIN\dba.personal.user SID (S-1-5-21-000000000-000000000-0000000000-00000) à partir de l'adresse LocalHost (à l'aide de LRPC) s'exécutant dans le conteneur d'application SID non disponible (non disponible). Cette autorisation de sécurité peut être modifiée à l'aide de l'outil d'administration des services de composants.
Cette erreur s'est produite environ 18 minutes avant le démarrage du processus de récupération par la base de données et s'est répétée parfois au début de la récupération. C'est quelque peu lié à l'utilisateur DBA, mais je ne sais vraiment pas ce que c'est (je n'ai pas encore eu le temps de demander le DBA).
Tout d'abord quelques règles de ménage.
Les deux liens suivants peuvent vous aider à mieux gérer le fichier journal des transactions.
Ce que vous rencontrez n'est pas un comportement normal lorsque le fichier journal des transactions est plein et ne peut pas se développer davantage.
Lorsque le journal des transactions est plein, le moteur de base de données SQL Server génère une erreur 9002. Le journal peut se remplir lorsque la base de données est en ligne ou en cours de récupération. Si le journal se remplit alors que la base de données est en ligne, la base de données reste en ligne mais ne peut être lue, pas mise à jour. Si le journal se remplit pendant la récupération, le moteur de base de données marque la base de données comme RESSOURCE EN ATTENTE. Dans les deux cas, une action de l'utilisateur est requise pour rendre l'espace de journal disponible.
La réponse appropriée à un journal de transactions complet dépend en partie de la ou des conditions qui ont amené le journal à se remplir. Pour découvrir ce qui empêche la troncature des journaux dans un cas donné, utilisez les colonnes log_reuse_wait et log_reuse_wait_desc de la vue de catalogue sys.database.
Ce que vous voyez, c'est l'échec de l'annulation des transactions. Pour plus de détails, lisez cet article.
Selon le blog de Paul Randal, vous avez rencontré un bogue qui a été corrigé dans SQL 2012 SP4.
Plus de détails sur l'erreur 3314:
Référence:
Voici mon point de vue sur votre problème:
Microsoft SQL Server 2012 (SP1) - 11.0.3156.0
Il s'agit d'une version assez ancienne et de nombreuses corrections ont été apportées aux nouveaux SP. Vous devez patcher votre serveur avec au moins SP4 - 11.00.7001 .
Erreur: 845. Gravité: 17. État: 1.
C'est votre sous-système de disque qui cause des problèmes. Vérifiez votre dossier \MSSQL\LOG\sqldump. Vous aurez créé des vidages de pile. Vous pouvez l'analyser selon délai d'expiration du verrou SQL Server Latch & Debugging ou ouvrir un dossier avec Microsoft. Vérifiez à nouveau votre sous-système de disque.
Erreur: 5901. Gravité: 16. État: 1
Ce problème a été résolu dans mise à jour cumulative 8 pour SQL Server 2012 SP2
donc plats à emporter:
La première et la plus importante chose que votre base de données est déjà en mode de récupération simple, donc le journal ne grandira pas beaucoup jusqu'à ce qu'il soit bloqué par une seule transaction. Une fois le point de contrôle arrivé, le journal sera tronqué lui-même. Maintenant que vous avez limité la taille du journal, SQL Server fait un tirage au sort lorsque la transaction est au milieu et qu'il n'y a plus de portée de journal à développer. Simplement conservée, la transaction a besoin du journal pour se développer. Vous ne pouvez pas terminer les transactions sans autoriser la croissance des journaux lorsque cela est nécessaire. C'est pourquoi le meilleur réglage est de garder la AUTOGROWTH activée.
SQL Server le traite comme un plantage, puis effectue une récupération pour restaurer les commandes incomplètes, comme indiqué dans le journal des erreurs.
Solution: activez l'AUTOGROWTH. De plus, s'il s'agit d'une base de données importante, passez en mode de récupération complète et configurez les sauvegardes de journaux.