web-dev-qa-db-fra.com

High Writelog Wait sur OLTP Système et stockage SSD rapide, la ruban-roulage est lente

nous avons récemment mis à niveau depuis SQL Server 2008 sur de nouveaux serveurs et mis à niveau vers SQL Server 2016 (SP1 CU3).

nouveau matériel de serveurs HP ProLiant 580G8, 4 Socket Intel Xeon E7 Processeur, total de 60 cœurs, 640 Go de RAM, 8 Intel SSD S3700 RAID 10, Local

l'environnement est un système anglais OLTP avec une requête par lots autour de 3k/seconde extrémité et à une mises à jour de degré de moindre degré. En tant que OLTP System il y a principalement 1 insert/transaction donc il y a beaucoup de commissions de transaction. Certaines requêtes de reporting sont des requêtes de rapport (lecteurs de file d'attente, surveillance, etc.)

le problème est que la performance de la rinçage est lente et nous obtenons Writelog Waits. J'ai testé des E/S et il peut gérer plus de 100 000 iops/sec dans un test d'écriture aléatoire 4K, écrit séquentiel jusqu'à 2500 Mo/sec

bases de données Niveau de compatibilité = 130 (SQL Server 2016)

point de contrôle indirect = sur,

VLF Nombre = 80-120

utilisation du processeur de processeur de 3% à 8%, moyenne de 5%, maxe à moins de 10% lorsque les sauvegardes de journal sont exécutées (sauvegardes comprimées) Temps de signal total/temps d'attente total = 6% - temps d'attente de ressources de 94% de ressources

memory Ple est sur le point de cocher chaque seconde, représente actuellement 584000 secondes, il y a très peu d'échange d'échange de pages observable (pages/sec)

c'est le vrai problème que j'ai trouvé

"LOG FUSHES/SEC" = 1000-2000/SEC

"Log Flush attend l'heure" = 1000-4000 MS/SEC

"journal de rinçage d'écriture" = 0-1 ms/sec avec des pointes de 10-15 ms/sec

"Disque AVG Sec/Ecrire" = 0

"File d'attente de disque actuelle" = 0 (avec pointes de 2 toutes les quelques minutes)

"Temps de ralenti disque" = 90% -100%

il semble donc que quelque chose ne va pas car SQL Server est incapable d'utiliser Ultra Faible latence que SSD Array fournit ...

j'ai essayé de désactiver les threads du journal du journal du masque d'affinité de la CPU, Chris Adkin a écrit dans son blog sans succès, également utilisé des événements étendus pour surveiller les flushes de journal et avoir vu plusieurs attentes se produit pour une seule rinçage de journaux.

je ne sais pas si ce problème existe sur les serveurs précédents, car sur cette plate-forme d'E/S était un peu problématique et "journal d'écriture de rinçage" était beaucoup plus haut ...

ainsi avez-vous déjà vu cette question sur le terrain et quelle est la solution à partir de maintenant merci

3
majid malek

Ce n'est pas une réponse pour 'Quelle est la solution à partir de maintenant' mais plus sur la manière d'identifier le problème.

Le journal des transactions ne ressemble pas aux pages de données en termes de fonctionnement du disque dur. Le journal des transactions est d'abord écrit pour enregistrer la mémoire tampon, puis décrits de manière asynchrone sur le disque. En 2016, il y a une limite de 112 i/OS de connexion de connexion simultanée à une fois pour le journal des transactions de chaque base de données.

Il y a 3 choses qui font que SQL Server ait besoin de rincer un tampon de journal sur le disque (à un bloc de journal adjacent dans le journal des transactions).

  1. Une transaction engage et cette transaction a un enregistrement de journal actif dans un tampon de journal. Cela provoquera toutes les enregistrements de journal dans ces tampons (à nouveau, jusqu'à 60 000 enregistrements de journal de transaction pour chaque tampon de journal) à rincer au fichier journal.
  2. Nous avons appuyé sur la limite de taille de 60k pour le tampon de journal et la rincir sur le disque.
  3. Nous avons des pages de données que nous devons écrire sur le disque et des enregistrements de journal sont liés à ces pages. Nous devons écrire ces enregistrements de journal au fichier journal avant d'écrire les pages de données dans les fichiers de données (cela prend en charge notre protocole de journalisation de l'écriture à l'avance (WAL)).

Le plus petit encolez-vous possible est un bloc de journal unique de 512 octets. Si toutes les transactions d'une charge de travail sont très petites (par exemple, insertion d'une seule ligne de table unique), il y aura de nombreuses fluctuations de journal de taille minimale. Les flushes de journal sont effectuées de manière asynchrone, pour permettre un débit de journal de transaction décent, mais il existe une limite fixe de 112 i/OS de rinçage simultanée à la fois.

Comme vous l'avez décrit, vous avez un bon sous-système IO conjointement avec un grand nombre de transactions courtes/sectes, votre problème peut être suivi.

Sur un sous-système d'E/S haute performance, les écrivies peuvent être complètes extrêmement rapidement, mais la limite de 112 I/OS de Log-Flush Crée un goulot d'étranglement lorsque vous essayez de faire enregistrer les enregistrements du journal sur le disque. Cette situation peut être identifiée par des latences d'écriture basse et un nombre presque constant de journal de transaction exceptionnelle écrit près de 112 dans la sortie agrégée de sys.dm_io_pending_io_requests.

La plupart de ce que j'ai mentionné ci-dessus proviennent des ressources suivantes et peu de solutions décrites. De plus, Paul Randal a une courte vidéo avec des scripts de démonstration pour confirmer si vous avez le problème que j'ai mentionné ci-dessus.

  1. surveillance du journal de transaction par Paul Randal
  2. coupe la partie grasse de la transaction grasse 1 par Paul
  3. couper plus de bûches de transaction FAT 2 par Paul Randal
  4. Qu'est-ce que IS SQL Server's IO taille de bloc? par Argenis Fernandez
  5. Vidéo par Paul Randal
  6. code de démonstration à utiliser avec la vidéo de Paul Randal
1
SqlWorldWide

(Pas une réponse, mais les commentaires n'autorisent pas le code.)

Vous n'avez pas de toujours AG ou un miroir, correct?

Dans une base de données d'utilisateurs, testez votre taux de rinçage de journal max comme suit:

create table t(id int)
go
set nocount on
declare @i int = 0
while @i < 100000
begin
  insert into t(id) values (@i);
  set @i = @i + 1;
end
0