SQL Server 2014 CTP1 въвежда опции за изчакване на заключване с нисък приоритет за използване с онлайн операции с индекси и превключватели на дялове.
За тези, които използват онлайн управление на индекси или операции за разделяне на индекси и превключване на дялове в SQL Server 2012 Enterprise Edition, може в един момент да сте изпитали блокиране на вашата DDL операция, тъй като тези операции все още имат някои изисквания за заключване.
За да илюстрираме, представете си, че изпълнявам следното онлайн възстановяване на индекс с един дял в SQL Server 2014 CTP1:
ПРОМЕНЯ ИНДЕКС [ClusteredIndex_on_ps_ShipDate]ВКЛ. [dbo].[FactInternetSales]ПРОИЗГРАЖДАНЕ НА ДЯЛА =(37)С (ONLINE=ВКЛЮЧЕНО);
И нека да разгледаме заключванията, придобити и освободени по време на тази операция за възстановяване с помощта на разширени събития и следната дефиниция на сесията (това е сесия без цел и аз гледах резултатите чрез панела „Watch Live Data“ в SQL Server Management Studio):
СЪЗДАВАНЕ НА СЪБИТИЯ СЕСИЯ [Online_Index_Rebuild_Locks_Taken] НА СЪРВЪР ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.lock_acquired( КЪДЕ ([object_id]=(309576141))),ДОБАВЯНЕ НА СЪБИТИЕ sqlserver.lock_released( 4))) MAX=WHERYME(WHERYME) 4096 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 СЕКУНДИ, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE>=);Стойността 309576141 представлява идентификатора на обекта на таблицата FactInternetSales.
Моето онлайн възстановяване на индекса на един дял отне 56 секунди, за да завърши и след завършването видях следната активност за придобиване и освобождаване на заключване:
Заключване на активност за онлайн повторно изграждане на един дялКакто можете да видите от изхода, въпреки че възстановяването е онлайн операция, то включва придобиване на ключалки в различни режими през жизнения цикъл на операцията. В идеалния случай продължителността на заключването е минимална (например – времевата марка е идентична за първия
SCH_S
заключване е придобито и освободено). Но дори и с минимално количество заключване, със сигурност можете да срещнете проблеми с едновременността в зависимост от транзакциите, изпълнявани срещу индекса, който се преизгражда или превключва.Споменах в началото на тази публикация, че Microsoft въведе опции за изчакване на заключване с нисък приоритет за онлайн операции и операции за превключване на дялове в SQL Server 2014 CTP1. По въпроса за превключвателите на дялове, представете си, че изпълнявам следната операция:
ПРОМЕНЯТ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[FactInternetSales] ПРЕВМЕСТИ ДЯЛ 37 КЪМ [AdventureWorksDW2012].[dbo].[staging_FactInternetSales];За да видя заключванията, придобити и освободени за тази операция, промених моята по-рано дефинирана сесия на разширено събитие, за да включа приложимите обекти (източна и целева таблица). Видях следното:
Заключване на активност за операция за превключване на дялОперацията по превключване към празен дял се случи за по-малко от секунда, но все още виждаме, че
SCH_S
иSCH_M
бяха необходими заключвания по време на жизнения цикъл на операцията както на източника, така и на местоназначението (309576141 е FactInternetSales и 398624463 е staging_FactInternetSales).Така че отново, докато продължителността на заключването може да бъде изключително кратка, когато няма едновременни транзакции за достъп до въпросните обекти, ние знаем, че това не винаги е възможно и така нашите онлайн операции за възстановяване на индекс и превключване на дялове наистина могат да бъдат блокирани.
Така че с тази реалност SQL Server 2014 въвежда
WAIT_AT_LOW_PRIORITY
аргумент, който може да се коригира сMAX_DURATION
иABORT_AFTER_WAIT
опции и за дватаALTER INDEX
иALTER TABLE
команди, които можем да използваме както за операции с онлайн индекс, така и за превключване на дялове.Какво ни позволява това да правим? Първо, нека поговорим за поведението преди SQL Server 2014. Като пример, представете си, че имам следната транзакция отворена и неангажирана:
ЗАПОЧНЕТЕ ТРАНЗАКЦИЯ;ИЗТРИВАНЕ [dbo].[staging_FactInternetSales];Ако се опитах да извърша
ALTER TABLE SWITCH
към таблицата staging_FactInternetSales като дестинация в отделна сесия, ще бъда блокиран и заявката просто ще изчака. Конкретно за този пример бих чакал сLCK_M_SCH_M
тип чакане. След като върна назад или завърша транзакцията си, операцията може да продължи напред и да завърши.Сега, ако използвам
WAIT_AT_LOW_PRIORITY
на SQL Server 2014 сMAX_DURATION
иABORT_AFTER_WAIT
, мога да използвам няколко различни опции в зависимост от изискванията на моето приложение.
MAX_DURATION
позволява ми да уточня броя минути, през които операцията за възстановяване на онлайн индекс или превключване на дялове ще изчака. АкоMAX_DURATION
стойността е достигната, можем да зададем какво ще се случи след това въз основа на настройката наABORT_AFTER_WAIT
, което може да бъде стойност наNONE
,SELF
илиBLOCKERS
:
NONE
означава, че операцията с индекс ще продължи да опитва операцията.SELF
означава, че акоMAX_DURATION
се достигне, операцията (онлайн възстановяването на индекса или превключвателят на дял) ще бъде отменена.- Ако
BLOCKERS
се използва, той ще убие всички транзакции, които блокират възстановяването на онлайн индекса или операцията за превключване на дялове (според мен не е опция, която да се използва с лека ръка).BLOCKERS
също така изискваALTER ANY CONNECTION
разрешение за заявката за издаване на онлайн възстановяване на индекс или операция за превключване на дял.
Следните примери за код демонстрират различни варианти на конфигурацията.
Поведение по подразбиране преди 2014 г. (изчакване за неопределено време)
- Изпълнението на следното ще доведе до поведението, което сме свикнали да виждаме пред-SQL Server 2014 – и все пак може да е това, което ще искате или очаквате за определени сценарии:
ПРОМЕНЯТЕ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[FactInternetSales] ПРЕКВЯНЕТЕ НА ДЯЛА 37 КЪМ [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY,MAX_T AWAMIN =NAPRIORITY, MAX_DMIN>);Изчакайте 1 минута и отменете DDL операцията
- Следният пример изчаква 1 минута, ако има блокираща транзакция и ще получи „периодът на изчакване на заявка за заключване е превишен“ за
SWITCH
операция, ако е достигната максималната продължителност: ПРОМЕНЯТЕ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[FactInternetSales] ПРЕВХОДНИ ДЯЛ 37 КЪМ [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY, MAX_T MIN_PRIORITY);Изчакайте 1 минута и убийте блокера(ите)
- Този пример изчаква 1 минута, ако има блокираща транзакция и след това ще убие блокиращите транзакции (включително източник или местоназначение), позволявайки на
SWITCH
операция за завършване. ПРОМЕНЯТЕ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] ПРЕКВЯНЕТЕ НА ДЯЛ 37 КЪМ [AdventureWorksDW2012].[dbo].[FactInternetSales] С (WAIT_AT_LOW_PRIORITY, MAX_T AWAMIN_PRIORITY, MAX_T AWAMIN_PRIORITY);В моя пример за
Съобщение 233, ниво 20, състояние 0, ред 3DELETE
вътре в неангажирана транзакция, нямаше грешка в прозореца на моя SQL Server Management Studio, тъй като нямах активно работещ израз, но опитът за друг израз в рамките на тази сесия върна следното съобщение за грешка (тъй като моята сесия беше убита):
При изпращане на заявката към сървъра е възникнала грешка на транспортно ниво. (доставчик:Доставчик на споделена памет, грешка:0 – Няма процес от другия край на тръбата.)Незабавно убийте блокиращия(ите)(и) (източник или дестинация за SWITCH)
- Следното е пример за незабавно унищожаване на блокера – и в моя пример превключването се случи за под-секунда и наистина сесията, която беше блокерът, беше убита:
ПРОМЕНЯТЕ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[FactInternetSales] ПРЕВМЪКНЕТЕ НА ДЯЛ 37 КЪМ [AdventureWorksDW2012].[dbo].[staging_FactInternetSales]СЪС (WAIT_AT_LOW_PRIORITY =PRE, MAX_T MIN_PRIORITY)Един последен положителен аспект, който исках да изтъкна...
Регистърът на грешките на SQL Server предоставя известен одит по подразбиране на използването на изчакване на заключване с нисък приоритет, включително информация за
Дата 9/10/2013 1:37:15 PMABORT_AFTER_WAIT
операция в съответствие с информацията за жертвата:
Регистрирайте SQL Server (текущи – 9/10/2013 12:03:00 PM)
Източник spid51
Съобщение
Процес Идентификатор 57 беше убит от ABORT_AFTER_WAIT =BLOCKERS DDL инструкция за database_id =5, object_id =309576141.Освен това ще видите отделни записи за самата оригинална операция. Например:
Инструкция ALTER TABLE SWITCH беше изпълнена в база данни 'AdventureWorksDW2012', таблица 'staging_FactInternetSales' по име на хост 'WIN-4T7S36VMSD9', идентификатор на хост процес 1360 с целева таблица 'AdventureWorksDW2012', използвайки опциите AdventureWorksDW2012'AtventureWorksDW2012, използвайки опциите 'AdventureWorksDW2012-MAX' =WAFACTERNET_WAFTERNET_WAFTERNET_WAFTERNET_WAFTERnet. БЛОКЕРИ. Блокирането на потребителски сесии ще бъде унищожено след максималната продължителност на времето за изчакване.Този вид регистриране е много полезен за целите на отстраняване на неизправности и одит и се радвам да го видя.