sql >> Database >  >> RDS >> Database

Gebeurtenisverlies begrijpen met uitgebreide gebeurtenissen

Mijn collega, Erin Stellato, stelde me onlangs een vraag over waar en waarom gebeurtenisverlies kan optreden met Extended Events. De vraag was het resultaat van een opmerking die iemand had gemaakt op een van haar blogposts waarin werd beweerd dat showplan_xml gebeurtenissen kunnen niet worden verzameld door de XE Profiler of via een "live" stream van de gebeurtenissen van de server. Ik weet toevallig dat dit niet correct is omdat ik routinematig de negatieve prestatie-effecten heb aangetoond van het gebruik van de post_query_execution_showplan-gebeurtenis tegen een productiebelasting door de gebeurtenis in de gebruikersinterface toe te voegen en de live-gegevens te laten bekijken, dus dit begon een meer diepgaande discussie over hoe en wanneer Extended Events een gebeurtenis verwijdert die is gegenereerd tijdens het verzamelen van gegevens.

Grootte van evenement is belangrijk

Extended Events configureert interne geheugenbufferruimte voor een gebeurtenissessie wanneer deze voor het eerst wordt gestart op de server, en de configuratie van de gebeurtenissessie-opties bepaalt hoe groot de geheugenbuffers zijn en de maximale gebeurtenisgrootte die de gebeurtenissessie kan verzamelen. Hoewel de meeste gebeurtenissen die door Extended Events worden gegenereerd relatief licht zijn en klein in binair formaat, kunnen specifieke gebeurtenissen een veel grotere lading aan gegevens genereren die moet worden gebufferd. De standaard opties voor gebeurtenissessies resulteren in een sessieconfiguratie met drie interne geheugenbuffers voor het vasthouden van gebeurtenissen die 1.441.587 bytes groot zijn. De grootte en het aantal geheugenbuffers voor een gebeurtenissessie kan worden gevonden in de sys.dm_xe_sessions DMV terwijl de sessie STATE=START op de server:

SELECT
    s.name, 
    s.total_regular_buffers,
    s.regular_buffer_size,
    s.total_large_buffers,
    s.large_buffer_size,
    s.total_buffer_size
FROM sys.dm_xe_sessions AS s;

Merk op dat er nul grote buffers zijn voor elk van de door het systeem gedefinieerde gebeurtenissessies, en dat de grote buffergrootte ook is ingesteld op nul, wat de standaardconfiguratie is. De grote buffers voor een gebeurtenissessie worden alleen gemaakt wanneer de sessieoptie MAX_EVENT_SIZE is geconfigureerd voor de gebeurtenissessie. De standaardwaarde voor deze optie is 0, wat betekent dat de grootste gebeurtenis die de gebeurtenissessie daadwerkelijk kan verbruiken, de grootte is van een normale geheugenbuffer, namelijk 1.441.587 bytes. Voor bepaalde gebeurtenissen, zoals diegene die de showplan_xml produceren, is het eigenlijk relatief eenvoudig om een ​​gebeurtenisgrootte te hebben die groter is dan de standaard geheugenbuffergrootte voor de gebeurtenissessie. In deze gevallen zou de grote gebeurtenis in feite worden weggegooid door de gebeurtenissessie, aangezien deze niet in een geheugenbuffer kan worden geplaatst voor verzending.

Gebeurtenisverlies beheersen

Er zijn drie specifieke sessie-opties die bepalen hoe groot een gebeurtenis een gebeurtenissessie daadwerkelijk kan verzamelen, en één die bepaalt hoe gebeurtenissen worden verwijderd wanneer het buffergeheugen voor de gebeurtenissessie vol is of onder druk staat. Deze zijn alle vier van belang als we het hebben over het verzamelen van evenementen die een grote evenementlading kunnen genereren en we willen de kans minimaliseren dat we een evenement kunnen laten vallen. Een voorbeeld van een gebeurtenissessie die vatbaar zou zijn voor gebeurtenisverlies als gevolg van geheugendruk in de bufferruimte voor de gebeurtenissessie staat hieronder:

CREATE EVENT SESSION [Locks] ON SERVER 
ADD EVENT sqlserver.lock_acquired,
ADD EVENT sqlserver.lock_released
ADD TARGET package0.event_file(SET filename=N'Locks',max_file_size=(5),max_rollover_files=(4))
WITH (MAX_MEMORY=4096 KB,
MEMORY_PARTITION_MODE=NONE,
EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_EVENT_SIZE=0 KB);

Opmerking:dit is geen evenementsessie die ik ooit zou aanraden om op een productiewerklast te draaien - de hoeveelheid gegevens die het zou genereren zou aanzienlijk zijn, omdat het elke vergrendeling bijhoudt die wordt verkregen en vrijgegeven.

Als we deze sessie starten en vervolgens de AdventureWorks Books Online Workload-generator uitvoeren die beschikbaar is op mijn blog tegen een exemplaar van SQL Server, zal de sessie snel beginnen met het verwijderen van gebeurtenissen vanwege de snelle gebeurtenisgeneratie en de vertraging in het doorspoelen van de buffer naar het event_file-doel dat is geconfigureerd. Het aantal gebeurtenissen dat door een gebeurtenissessie is verwijderd, kan worden bijgehouden in de DMV sys.dm_xe_sessions als de opties voor gebeurtenissessies zijn geconfigureerd met EVENT_RETENTION_MODE =ALLOW_SINGLE_EVENT_LOSS. Als de gebeurtenissessie is geconfigureerd met EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS, kunnen volledige geheugenbuffers van gebeurtenissen worden verwijderd en telt het alleen hoeveel buffers zijn verwijderd en niet het aantal afzonderlijke gebeurtenissen dat elke buffer bevat.

SELECT
   s.name, 
   s.total_regular_buffers,
   s.regular_buffer_size,
   s.total_large_buffers,
   s.large_buffer_size,
   s.dropped_event_count,
   s.dropped_buffer_count,
   s.largest_event_dropped_size
FROM sys.dm_xe_sessions AS s;

Hier kunnen we zien dat 100.521 gebeurtenissen zijn verwijderd en de grootste grootte van een gebeurtenis die is verwijderd, was 176 bytes, wat kleiner is dan de grootte van onze normale bufferruimte, dus we raken gewoon de normale druk van de buffergeheugenruimte. Als we echter een gebeurtenissessie maken die de twee showplan-gebeurtenissen verzamelt (zie dit artikel waarom dit de prestaties ernstig negatief zal beïnvloeden en niet op productieservers zou moeten worden gedaan), samen met de batchstart- en voltooide gebeurtenissen en enkele grotere plannen, kunnen we gebeurtenisverlies veroorzaken vanwege de grootte van het evenement.

CREATE EVENT SESSION [DropsEvents] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan,
ADD EVENT sqlserver.query_pre_execution_showplan,
ADD EVENT sqlserver.sql_batch_completed,
ADD EVENT sqlserver.sql_batch_starting;

Hier kunnen we zien dat de grootste_event_dropped_size groter is dan onze regular_buffer_size, dus dit betekent dat we de configuratie van onze sessiebuffers moeten wijzigen. Als we de MAX_MEMORY voor de gebeurtenissessie verhogen, kan dit de grootte van onze reguliere buffers vergroten. De standaardwaarde is slechts 4 MB, waar de hierboven getoonde buffergrootte van 1,4 MB vandaan komt. Als we dit wijzigen in 64 MB voor de gebeurtenissessie, zal de regular_buffer_size 22,4 MB groot zijn, wat plaats zou bieden aan onze 3,7 MB verwijderde gebeurtenis. De andere optie is om de MAX_EVENT_SIZE optie in te stellen die de large_buffer_size levert voor grote evenementen en wordt gedeeld door twee voor de sessie.

CREATE EVENT SESSION [CollectsEvents] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan,
ADD EVENT sqlserver.query_pre_execution_showplan,
ADD EVENT sqlserver.sql_batch_completed,
ADD EVENT sqlserver.sql_batch_starting
WITH (MAX_MEMORY=65536 KB,MAX_EVENT_SIZE=65536 KB,MEMORY_PARTITION_MODE=NONE);

Dus hier kunnen we de twee grote buffers zien met een grootte van 33,6 MB en nadat we hetzelfde plan opnieuw hebben uitgevoerd om de werklast te genereren, hebben we geen verwijderde gebeurtenissen voor onze nieuwe CollectsEvents-sessie, maar we hebben de verwijderde gebeurtenissen voor onze DropsEvents-sessie verdubbeld met behulp van de standaardinstellingen.

Dus daar heb je het; waarom bepaalde gebeurtenissen mogelijk niet worden verzameld door een gebeurtenissessie, hoe u problemen kunt oplossen wanneer gebeurtenissen worden verwijderd en hoe u kunt bepalen of de grootte van de gebeurtenis het probleem veroorzaakt. Veel van de sessies die ik daadwerkelijk gebruik op clientsystemen, hebben de standaardinstellingen voor opties voor gebeurtenissessies, vooral als het om geheugen gaat. Dit is een gebied dat, zodra u het buffermechanisme dat door Extended Events wordt gebruikt begrijpt en vervolgens de omvang van de mogelijk gegenereerde gebeurtenissen in overweging neemt, u begint met het aanbrengen van wijzigingen in de manier waarop de sessie-opties worden gedefinieerd om de kans op gebeurtenissen te minimaliseren. wordt verwijderd vanwege limieten voor geheugenruimte of beperking van de gebeurtenisgrootte.


  1. SQLite-vallen en valkuilen

  2. Is er een manier om het rijnummer in Mysql te krijgen, zoals het rijnummer in orakel?

  3. Hoe sp_describe_first_result_set werkt in SQL Server

  4. Hoe voorloop- en volgspaties in SQL Server te verwijderen – TRIM()