Тұйық және құлыптардағы кілт пен бет күту ресурсын дешифрлеу

Егер сіз бұғатталған процесс есебін пайдалансаңыз немесе SQL Server ұсынатын тұйықталу графиктерін мерзімді түрде жинасаңыз, келесідей нәрселерге тап боласыз:

waitresource="БЕТ: 6:3:70133"

waitresource=“KEY: 6:72057594041991168 (ce52f92a058c)“

Кейде сіз зерттейтін алып XML-де көбірек ақпарат болады (тұйықталған графиктерде объект және индекс атауларын табуға көмектесетін ресурстар тізімі бар), бірақ әрқашан емес.

Бұл мәтін оларды шешуге көмектеседі.

Мұндағы барлық ақпарат Интернетте әртүрлі жерлерде бар, ол жай ғана таратылады! DBCC PAGE бастап hobt_id және құжатталмаған %%physloc%% және %%lockres%% функцияларына дейін барлығын біріктіргім келеді.

Алдымен, PAGE құлыптарындағы күтулер туралы сөйлесейік, содан кейін KEY құлыптарына көшейік.

1) waitresource="PAGE: 6:3:70133" = Database_Id: FileId: PageNumber

Егер сұрауыңыз БЕТ құлпын күтсе, SQL сервері сізге сол беттің мекенжайын береді.

"PAGE: 6:3:70133" бөлімін бөлсек, біз мынаны аламыз:

  • дерекқор_идентификаторы = 6
  • data_file_id = 3
  • бет_нөмірі = 70133

1.1) database_id шифрын шешу

Сұраныс арқылы мәліметтер қорының атын табыңыз:

SELECT 
    name 
FROM sys.databases 
WHERE database_id=6;
GO

Бұл қоғамдық DB WideWorldImporters менің SQL серверімде.

1.2) Деректер файлының атын іздеу - егер сізді қызықтырса

Келесі қадамда кесте атын табу үшін data_file_id қолданамыз. Сіз жай ғана келесі қадамға өтіп кете аласыз, бірақ егер сізді файл атауы қызықтырса, оны осы сұрауға data_file_id ауыстырып, табылған дерекқор контекстінде сұрауды іске қосу арқылы таба аласыз:

USE WideWorldImporters;
GO
SELECT 
    name, 
    physical_name
FROM sys.database_files
WHERE file_id = 3;
GO

WideWorldImporters дерекқорында бұл WWI_UserData деп аталатын файл және мен оны C:MSSQLDATAWideWorldImporters_UserData.ndf қалпына келтірдім. (Ой, сіз мені жүйелік дискіге файлдарды салып жатқанда ұстадыңыз! Жоқ! Бұл ұят).

1.3) DBCC PAGE ішінен нысан атауын алыңыз

Біз қазір 70133-деректер файлындағы №3 бет WorldWideImporters дерекқорына жататынын білеміз. Біз бұл беттің мазмұнын құжатталмаған DBCC PAGE және 3604 бақылау жалауын пайдаланып қарай аламыз.
Ескерту: Мен басқа сервердегі қалпына келтірілген көшірмеде DBCC PAGE пайдаланғым келеді, себебі бұл құжатталмаған материал. Кейбір жағдайларда ол қоқысқа әкелуі мүмкін (шамамен. аудармашы - сілтеме, өкінішке орай, ешқайда апармайды, бірақ url-ге қарағанда, біз сүзгіленген индекстер туралы айтып отырмыз.).

/* This trace flag makes DBCC PAGE output go to our Messages tab
instead of the SQL Server Error Log file */
DBCC TRACEON (3604);
GO
/* DBCC PAGE (DatabaseName, FileNumber, PageNumber, DumpStyle)*/
DBCC PAGE ('WideWorldImporters',3,70133,2);
GO

Нәтижелерге жылжу арқылы сіз object_id және index_id таба аласыз.
Тұйық және құлыптардағы кілт пен бет күту ресурсын дешифрлеу
Бітуге сәл қалды бітейін деп қалдым! Енді кесте мен индекс атауларын сұрау арқылы таба аласыз:

USE WideWorldImporters;
GO
SELECT 
    sc.name as schema_name, 
    so.name as object_name, 
    si.name as index_name
FROM sys.objects as so 
JOIN sys.indexes as si on 
    so.object_id=si.object_id
JOIN sys.schemas AS sc on 
    so.schema_id=sc.schema_id
WHERE 
    so.object_id = 94623380
    and si.index_id = 1;
GO

Мұнда біз құлыпта күту Sales.OrderLines кестесінің PK_Sales_OrderLines индексінде болғанын көреміз.

Ескерту: SQL Server 2014 және одан жоғары нұсқаларында нысан атауын құжатталмаған DMO sys.dm_db_database_page_allocations арқылы да табуға болады. Бірақ сіз дерекқордағы әрбір бетті сұрауыңыз керек, бұл үлкен дерекқорлар үшін өте жақсы көрінбейді, сондықтан мен DBCC PAGE қолдандым.

1.4) Бұғатталған бетте деректерді көруге болады ма?

Нууу, иә. Бірақ... бұл сізге шынымен керек екеніне сенімдісіз бе?
Тіпті кішкентай үстелдерде де баяу. Бірақ бұл өте керемет, сондықтан сіз осы уақытқа дейін оқығаныңыз үшін...%%physloc%% туралы сөйлесейік!

%%physloc%% — әрбір жазба үшін физикалық идентификаторды қайтаратын құжатталмаған сиқыр бөлігі. пайдалана аласыз %%physloc%% және SQL Server 2008 және кейінгі нұсқаларында sys.fn_PhysLocFormatter.

Енді Sales.OrderLines ішіндегі бетті бұғаттауды қалайтынымызды білгендіктен, №3 бетіндегі №70133 деректер файлында сақталған осы кестедегі барлық деректерді келесі сұраумен қарай аламыз:

Use WideWorldImporters;
GO
SELECT 
    sys.fn_PhysLocFormatter (%%physloc%%),
    *
FROM Sales.OrderLines (NOLOCK)
WHERE sys.fn_PhysLocFormatter (%%physloc%%) like '(3:70133%'
GO

Мен айтқанымдай, ол тіпті кішкентай үстелдерде де баяу. Мен сұрауға NOLOCK қостым, себебі бізде әлі де қарастырғымыз келетін деректердің құлып табылған кездегідей екеніне кепілдік жоқ - осылайша біз лас оқуларды қауіпсіз жасай аламыз.
Бірақ, өкінішке орай, сұрау маған сұрауымыз күрескен 25 жолды қайтарады.
Тұйық және құлыптардағы кілт пен бет күту ресурсын дешифрлеу
PAGE құлыптары туралы жеткілікті. Егер біз KEY құлпын күтсек ше?

2) waitresource="KEY: 6:72057594041991168 (ce52f92a058c)" = Database_Id, HOBT_Id (егер шынымен қаласаңыз, %%lockres%% шифрын шешуге болатын сиқырлы хэш)

Сұрауыңыз индекстік жазбаны құлыптауға әрекеттенсе және өздігінен құлыпталса, сіз мүлдем басқа мекенжай түрін аласыз.
«6:72057594041991168 (ce52f92a058c)» бөліктерге бөлсек, біз мынаны аламыз:

  • дерекқор_идентификаторы = 6
  • hobt_id = 72057594041991168
  • сиқырлы хэш = (ce52f92a058c)

2.1) database_id шифрын шешу

Ол жоғарыдағы мысалмен бірдей жұмыс істейді! Мәліметтер қорының атын сұрау арқылы табамыз:

SELECT 
    name 
FROM sys.databases 
WHERE database_id=6;
GO

Менің жағдайда, бұл бірдей DB WideWorldImporters.

2.2) hobt_id шифрын шешіңіз

Табылған дерекқордың контекстінде кесте мен индекстің атауларын анықтауға көмектесетін бірнеше қосылымдары бар sys.partitions сұрауы керек ...

USE WideWorldImporters;
GO
SELECT 
    sc.name as schema_name, 
    so.name as object_name, 
    si.name as index_name
FROM sys.partitions AS p
JOIN sys.objects as so on 
    p.object_id=so.object_id
JOIN sys.indexes as si on 
    p.index_id=si.index_id and 
    p.object_id=si.object_id
JOIN sys.schemas AS sc on 
    so.schema_id=sc.schema_id
WHERE hobt_id = 72057594041991168;
GO

Бұл сұраудың PK_Application_Countries индексін қолданатын Application.Countries құлыптауында күтіп тұрғанын айтады.

2.3) Енді кейбір %%lockres%% сиқыр үшін - егер сіз қай жазба құлыпталғанын білгіңіз келсе

Егер мен шынымен құлыптың қай қатарда қажет екенін білгім келсе, кестенің өзінен сұрау арқылы біле аламын. Біз сиқырлы хэшке сәйкес жазбаны табу үшін құжатталмаған %%lockres%% функциясын пайдалана аламыз.
Бұл сұрау бүкіл кестені сканерлейтінін және үлкен кестелерде бұл қызықты болмауы мүмкін екенін ескеріңіз:

SELECT
    *
FROM Application.Countries (NOLOCK)
WHERE %%lockres%% = '(ce52f92a058c)';
GO

Мен NOLOCK қостым (Твиттердегі Клаус Ашенбреннердің кеңесі бойынша) себебі құлыптар проблема болуы мүмкін. Біз транзакция басталған кезде не болғанын емес, қазір не бар екенін көргіміз келеді - деректердің сәйкестігі біз үшін маңызды деп ойламаймын.
Войла, біз күрескен рекорд!
Тұйық және құлыптардағы кілт пен бет күту ресурсын дешифрлеу

Алғыс және әрі қарай оқу

Бұл заттардың көпшілігін кім алғаш рет сипаттағаны есімде жоқ, бірақ мұнда сізге ұнайтын ең аз құжатталған нәрселер туралы екі хабарлама бар:

Ақпарат көзі: www.habr.com

пікір қалдыру