Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Изследване на опциите за изчакване на заключване с нисък приоритет в SQL Server 2014 CTP1

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); 

      В моя пример за DELETE вътре в неангажирана транзакция, нямаше грешка в прозореца на моя SQL Server Management Studio, тъй като нямах активно работещ израз, но опитът за друг израз в рамките на тази сесия върна следното съобщение за грешка (тъй като моята сесия беше убита):

      Съобщение 233, ниво 20, състояние 0, ред 3
      При изпращане на заявката към сървъра е възникнала грешка на транспортно ниво. (доставчик:Доставчик на споделена памет, грешка:0 – Няма процес от другия край на тръбата.)

    Незабавно убийте блокиращия(ите)(и) (източник или дестинация за SWITCH)

      Следното е пример за незабавно унищожаване на блокера – и в моя пример превключването се случи за под-секунда и наистина сесията, която беше блокерът, беше убита:

      ПРОМЕНЯТЕ ТАБЛИЦА [AdventureWorksDW2012].[dbo].[FactInternetSales] ПРЕВМЪКНЕТЕ НА ДЯЛ 37 КЪМ [AdventureWorksDW2012].[dbo].[staging_FactInternetSales]СЪС (WAIT_AT_LOW_PRIORITY =PRE, MAX_T MIN_PRIORITY) 

Един последен положителен аспект, който исках да изтъкна...

Регистърът на грешките на SQL Server предоставя известен одит по подразбиране на използването на изчакване на заключване с нисък приоритет, включително информация за ABORT_AFTER_WAIT операция в съответствие с информацията за жертвата:

Дата 9/10/2013 1:37:15 PM
Регистрирайте 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. БЛОКЕРИ. Блокирането на потребителски сесии ще бъде унищожено след максималната продължителност на времето за изчакване.

Този вид регистриране е много полезен за целите на отстраняване на неизправности и одит и се радвам да го видя.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Съхранена процедура за SQL повикване за всеки ред без използване на курсор

  2. Как работи функцията STR() в SQL Server (T-SQL)

  3. Използване на DBCC CLONEDATABASE за генериране на схема и статистически копие само на потребителска база данни в SQL Server 2014 SP2

  4. SQL RANK() срещу ROW_NUMBER()

  5. Анализирайте низ, разделен със запетая, за да направите IN Списък на низовете в клаузата Where