Leyndu lykil og Page WaitResource í lásum og læsingum

Ef þú notar lokuðu ferlisskýrsluna eða safnar grafík sem SQL Server gefur reglulega, muntu lenda í hlutum eins og þessu:

waitresource="SÍÐA: 6:3:70133"

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

Stundum verða meiri upplýsingar í þessum risastóra XML sem þú rannsakar (deadlock grafs innihalda lista yfir tilföng sem hjálpa þér að finna nöfn hlutarins og vísitöluna), en ekki alltaf.

Þessi texti mun hjálpa þér að ráða þær.

Allar upplýsingar sem eru hér eru á netinu á ýmsum stöðum, þær eru einfaldlega mjög dreifðar! Ég vil setja þetta allt saman, frá DBCC PAGE til hobt_id til óskráðu %%physloc%% og %%lockres%% aðgerðanna.

Í fyrsta lagi skulum við tala um bið á PAGE læsingum og fara síðan yfir í KEY læsingar.

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

Ef beiðni þín bíður á PAGE læsingu mun SQL Server gefa þér heimilisfang þeirrar síðu.

Ef við sundurliðum „PAGE: 6:3:70133“ fáum við:

  • database_id = 6
  • data_file_id = 3
  • síðunúmer = 70133

1.1) Afkóða database_id

Finndu nafn gagnagrunnsins með því að nota fyrirspurnina:

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

Það er opinbert DB WideWorldImporters á SQL Servernum mínum.

1.2) Ertu að leita að nafni gagnaskrárinnar - ef þú hefur áhuga

Við ætlum að nota data_file_id í næsta skrefi til að finna töfluheitið. Þú getur bara sleppt næsta skrefi, en ef þú hefur áhuga á skráarnafninu geturðu fundið það með því að keyra fyrirspurn í samhengi við gagnagrunninn sem fannst og setja data_file_id í staðinn fyrir þessa fyrirspurn:

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

Í WideWorldImporters gagnagrunninum er þetta skrá sem heitir WWI_UserData og ég hef hana endurheimt í C:MSSQLDATAWideWorldImporters_UserData.ndf. (Úbbs, þú náðir mér í að setja skrár á kerfisdrifið! Nei! Það er vandræðalegt).

1.3) Fáðu nafn hlutar frá DBCC PAGE

Við vitum núna að síða #70133 í gagnaskrá 3 tilheyrir WorldWideImporters gagnagrunninum. Við getum skoðað innihald þessarar síðu með því að nota óskráðu DBCC PAGE og rekja fána 3604.
Athugið: Ég kýs að nota DBCC PAGE á endurheimtu eintaki einhvers staðar á öðrum netþjóni, vegna þess að það er óskráð efni. Í sumum tilfellum, hún getur leitt til sorphauga (ca. þýðandi - hlekkurinn leiðir því miður hvergi, en miðað við slóðina erum við að tala um síaðar vísitölur).

/* 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

Með því að fletta að niðurstöðunum geturðu fundið object_id og index_id.
Leyndu lykil og Page WaitResource í lásum og læsingum
Næstum lokið! Nú geturðu fundið töflu- og vísitöluheitin með fyrirspurn:

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

Og hér sjáum við að biðin á lásnum var á PK_Sales_OrderLines vísitölunni í Sales.OrderLines töflunni.

Athugið: Í SQL Server 2014 og nýrri er einnig hægt að finna nafn hlutar með því að nota óskráða DMO sys.dm_db_database_page_allocations. En þú þarft að spyrjast fyrir um hverja síðu í gagnagrunninum, sem lítur ekki mjög flott út fyrir stóra gagnagrunna, svo ég notaði DBCC PAGE.

1.4) Er hægt að sjá gögnin á síðunni sem var læst?

Nuuu, já. En… ertu viss um að þú þurfir þess virkilega?
Það er hægt jafnvel á litlum borðum. En það er soldið töff, svo þar sem þú hefur lesið þetta langt...talum við um %%physloc%%!

%%physloc%% er óskráður töfraþáttur sem skilar líkamlegu auðkenni fyrir hverja færslu. þú getur notað %%physloc%% ásamt sys.fn_PhysLocFormatter í SQL Server 2008 og síðar.

Nú þegar við vitum að við vildum loka á síðuna í Sales.OrderLines getum við skoðað öll gögnin í þessari töflu, sem er geymd í gagnaskrá #3 á síðu #70133, með eftirfarandi fyrirspurn:

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

Eins og ég sagði, það er hægt jafnvel á pínulitlum borðum. Ég bætti NOLOCK við beiðnina vegna þess að við höfum enn engar tryggingar fyrir því að gögnin sem við viljum skoða séu nákvæmlega þau sömu og þau voru þegar læsingin uppgötvaðist - svo við getum örugglega gert óhreinar lestur.
En, húrra, fyrirspurnin skilar mér einmitt þeim 25 línum sem fyrirspurnin okkar barðist fyrir.
Leyndu lykil og Page WaitResource í lásum og læsingum
Nóg um PAGE læsingar. Hvað ef við erum að bíða eftir LYKLAlás?

2) waitresource="KEY: 6:72057594041991168 (ce52f92a058c)" = Database_Id, HOBT_Id (töfrahash sem hægt er að afkóða með %%lockres%% ef þú vilt virkilega)

Ef fyrirspurn þín reynir að læsa vísitölufærslu og læsist ein og sér færðu allt aðra tegund af heimilisfangi.
Ef „6:72057594041991168 (ce52f92a058c)“ er skipt í hluta, fáum við:

  • database_id = 6
  • hobt_id = 72057594041991168
  • galdrakássa = (ce52f92a058c)

2.1) Afkóða database_id

Það virkar nákvæmlega eins og með dæminu hér að ofan! Við finnum nafn gagnagrunnsins með því að nota fyrirspurnina:

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

Í mínu tilfelli er það sama DB WideWorldImporters.

2.2) Afkóða hobt_id

Í samhengi við fundinn gagnagrunn þarftu að spyrjast fyrir um sys.partitions með nokkrum tengingum sem hjálpa til við að ákvarða nöfn töflunnar og vísitölu ...

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

Það segir mér að beiðnin hafi beðið á Application.Countries læsingunni með því að nota PK_Application_Countries vísitöluna.

2.3) Nú fyrir einhvern %%lockres%% galdra - ef þú vilt komast að því hvaða færslu var læst

Ef mig langar virkilega að vita á hvaða röð lásinn var þörf get ég komist að því með því að spyrjast fyrir í töflunni sjálfri. Við getum notað óskráðu %%lockres%% aðgerðina til að finna færslu sem passar við töfrahasið.
Athugaðu að þessi fyrirspurn mun skanna alla töfluna og á stórum borðum gæti þetta alls ekki verið skemmtilegt:

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

ég bætti við NOLOCK (að ráði Klaus Aschenbrenner á twitter) vegna þess að læsingar geta verið vandamál. Við viljum bara skoða hvað er til staðar núna, en ekki hvað var þar þegar viðskiptin hófust - ég held að gagnasamkvæmni sé ekki mikilvæg fyrir okkur.
Voila, metið sem við börðumst fyrir!
Leyndu lykil og Page WaitResource í lásum og læsingum

Þakkir og frekari lestur

Ég man ekki hver lýsti mörgum af þessum hlutum fyrst, en hér eru tvær færslur um það sem minnst er skjalfest sem þér gæti líkað:

Heimild: www.habr.com

Bæta við athugasemd