Моят колега, Ерин Стелато, наскоро ми зададе въпрос за това къде и защо може да се случи загуба на събитие с разширени събития. Въпросът е резултат от коментар, който някой е направил към една от публикациите й в блога, който твърди, че showplan_xml
събитията не могат да бъдат събирани от XE Profiler или чрез „на живо“ поток от събитията от сървъра. Случайно знам, че това не е правилно, защото рутинно демонстрирах отрицателните въздействия върху производителността от използването на събитието post_query_execution_showplan срещу производствено натоварване, като добавих събитието в потребителския интерфейс и го накарах да гледа данните на живо, така че това започна по-задълбочена дискусия за това как и кога Разширените събития ще отхвърлят събитие, което е било генерирано по време на събирането на данни.
Размерът на събитието има значение
Разширените събития конфигурират вътрешното буферно пространство на паметта за сесия на събитие, когато тя е стартирана първоначално на сървъра, а конфигурацията на опциите за сесия на събитието определя колко големи са буферите на паметта и максималния размер на събитието, което сесията на събитието може да събере. Докато повечето събития, генерирани от разширени събития, са относително леки и малки в двоичен формат, специфични събития могат да генерират много по-голям полезен товар от данни, които трябва да бъдат буферирани. Опциите за сесия за събития по подразбиране водят до конфигурация на сесия с три буфера на вътрешна памет за задържане на събития с размер 1 441 587 байта. Размерът и броят на буферите на паметта за сесия на събитие могат да бъдат намерени в sys.dm_xe_sessions DMV, докато сесията STATE=START на сървъра:
SELECT s.name, s.total_regular_buffers, s.regular_buffer_size, s.total_large_buffers, s.large_buffer_size, s.total_buffer_sizeFROM sys.dm_xe_sessions AS;
Забележете, че има нула големи буфери за всяка от сесиите, дефинирани от системата, и големият размер на буфера също е настроен на нула, което е конфигурацията по подразбиране. Големите буфери за сесия на събитие се създават само когато опцията за сесия MAX_EVENT_SIZE е конфигурирана за сесията на събитието. Стойността по подразбиране за тази опция е 0, което означава, че най-голямото събитие, което сесията на събитието може действително да приеме, е размерът на обикновен буфер на паметта, който е 1 441 587 байта. За определени събития, като тези, които произвеждат showplan_xml, всъщност е сравнително лесно да имате размер на събитие, който е по-голям от размера на буфера на паметта по подразбиране за сесията на събитието. В тези случаи голямото събитие всъщност ще бъде изхвърлено от сесията на събитието, тъй като не може да бъде поставено в буфер на паметта за изпращане.
Контролиране на загубата на събитие
Има три специфични опции за сесия, които определят колко голямо събитие може действително да събере една сесия на събитие и една, която контролира как събитията се отпадат, когато буферната памет за сесията на събитието е пълна или под налягане. И четирите от тях имат значение, когато говорим за събиране на събития, които биха могли да генерират голям полезен товар и искаме да сведем до минимум шанса, че потенциално можем да пропуснем събитие. Примерна сесия на събитие, която би била предразположена към загуба на събитие поради натиска на паметта в буферното пространство за сесията на събитието, е по-долу:
СЪЗДАВАНЕ НА СЕСИЯ НА СЪБИТИЕ [Заключвания] НА СЪРВЪР ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.lock_acquired,ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.lock_releasedADD TARGET package0.event_file(SET filename=N'Locks',max_file_size=(5),max_file_size=(5),max_file_size=(5),max_file_roll=(5)max_roll(over_file) =4096 KB,MEMORY_PARTITION_MODE=НЯМА,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_EVENT_SIZE=0 KB);
Забележка:Това не е сесия за събитие, която бих препоръчал да се изпълнява при производствено натоварване – обемът данни, който би генерирал, би бил значителен, тъй като проследява всяко придобиване и освобождаване на заключване.
Ако стартираме тази сесия и след това стартираме генератора на AdventureWorks Books Online Workload, който е наличен в моя блог срещу екземпляр на SQL Server, сесията бързо ще започне да отпада събития поради бързото генериране на събития и забавянето на прочистването на буфера към целта на event_file който е конфигуриран. Броят на събитията, отпаднали от сесия на събитие, може да бъде проследен в sys.dm_xe_sessions DMV, ако опциите на сесията на събитието са конфигурирани с EVENT_RETENTION_MODE =ALLOW_SINGLE_EVENT_LOSS. Ако сесията на събитието е конфигурирана с EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS, тогава цели буфери на паметта на събитията могат да бъдат отхвърлени и отчита само колко буфера са били изпуснати, а не броя на отделните събития, съдържащи се във всеки буфер.
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_sizeFROM sys.dm_x sys.dm_x;
Тук можем да видим, че 100 521 събития са отпаднали и най-големият размер на събитие, което е изпуснато, е 176 байта, което е по-малко от размера на нашето редовно буферно пространство, така че просто удряме нормалното налягане в пространството на буферната памет. Въпреки това, ако създадем сесия за събитие, която събира двете от събитията на showplan (вижте тази статия защо това ще повлияе сериозно на производителността и не трябва да се прави на производствени сървъри), заедно с пакетните стартиращи и завършени събития и генериране на някои по-големи планове, можем да предизвикаме загуба на събитие поради размера на събитието.
СЪЗДАВАНЕ НА СЪБИТИЯ [DropsEvents] НА СЪРВЪР ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.query_post_execution_showplan,ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.query_pre_execution_showplan,ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.sql_batch_completed,sql_batch_completed,sql_batch_completed.
Тук можем да видим, че large_event_dropped_size е по-голям от нашия regular_buffer_size, така че това означава, че трябва да променим конфигурацията на нашите буфери за сесия. Ако увеличим MAX_MEMORY за сесията на събитието, това може да увеличи размера на нашите редовни буфери. Стойността по подразбиране е само 4MB, откъдето идва размерът на буфера от 1,4MB, показан по-горе. Ако променим това на 64MB за сесията на събитието, regular_buffer_size ще бъде с размер 22,4MB, което ще побере нашето отпаднало събитие от 3,7MB. Другата опция е да зададете опцията MAX_EVENT_SIZE, която предоставя large_buffer_size за големи събития и се дели на две за сесията.
Създаване на сесия за събития [CollectSvents] На сървър Добавяне на събитие SQLSERVER.QUERY_POST_EXECUTION_SHOWPLAN, Добавяне на събитие sqlserver.query_pre_execution_showplan, добавяне на събитие sqlserver.sql_batch_completed, добавяне на evet sqlserver.sql_batch_completed, добавяне на evet sqlserver.sql_batch_completed, добавяне на evet sqlserver.sql_batch_completed, добавяне
Така че тук можем да видим двата големи буфера с размер 33.6MB и след като стартираме същия план, генериращ отново работно натоварване, нямаме пропуснати събития за новата ни сесия CollectsEvents, но удвоихме изпуснатите събития за нашата сесия DropsEvents, използвайки настройките по подразбиране.
И така, ето го; защо някои събития може да не бъдат събрани от сесия на събитие, как да се предприеме отстраняване на неизправности, когато събитията се отпадат, и как да се определи дали размерът на събитието причинява проблема. Много от сесиите, които виждам в действителна употреба в клиентски системи, имат настройките по подразбиране за опциите за сесия на събития, особено когато става въпрос за памет. Това е една област, в която след като разберете механизма за буфериране, използван от разширени събития, и след това вземете предвид размера на събитията, които потенциално биха могли да бъдат генерирани, ще започнете да правите промени в начина, по който се дефинират опциите за сесия, за да минимизирате потенциала за събития отпада поради ограничения на пространството в паметта или ограничения на размера на събитието.