Menghurai Kunci dan Halaman WaitResource dalam kebuntuan dan kunci

Jika anda menggunakan laporan proses yang disekat atau mengumpul graf kebuntuan yang disediakan oleh SQL Server secara berkala, anda akan menghadapi perkara seperti ini:

waitresource="PAGE: 6:3:70133"

waitresource=β€œKEY: 6:72057594041991168 (ce52f92a058c)β€œ

Kadangkala, terdapat lebih banyak maklumat dalam XML gergasi yang anda pelajari (graf kebuntuan mengandungi senarai sumber yang membantu anda mengetahui nama objek dan indeks), tetapi tidak selalu.

Teks ini akan membantu anda menguraikannya.

Semua maklumat yang ada di sini ada di Internet di pelbagai tempat, ia sangat diedarkan! Saya ingin menggabungkan semuanya, daripada DBCC PAGE hingga hobt_id kepada fungsi %%physloc%% dan %%lockres%% yang tidak didokumenkan.

Mula-mula, mari bercakap tentang menunggu pada kunci PAGE, dan kemudian beralih ke kunci KEY.

1) waitresource="PAGE: 6:3:70133" = Id_Pangkalan Data: Id Fail: Nombor Halaman

Jika permintaan anda menunggu pada kunci PAGE, SQL Server akan memberikan anda alamat halaman tersebut.

Memecahkan "HALAMAN: 6:3:70133" kita dapat:

  • id_pangkalan data = 6
  • data_fail_id = 3
  • nombor_muka surat = 70133

1.1) Nyahsulit pangkalan data_id

Cari nama pangkalan data menggunakan pertanyaan:

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

Ia awam DB WideWorldImporters pada Pelayan SQL saya.

1.2) Mencari nama fail data - jika anda berminat

Kami akan menggunakan data_file_id dalam langkah seterusnya untuk mencari nama jadual. Anda boleh melangkau ke langkah seterusnya, tetapi jika anda berminat dengan nama fail, anda boleh menemuinya dengan menjalankan pertanyaan dalam konteks pangkalan data yang ditemui, menggantikan data_file_id ke dalam pertanyaan ini:

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

Dalam pangkalan data WideWorldImporters ini ialah fail yang dipanggil WWI_UserData dan saya telah memulihkannya kepada C:MSSQLDATAWideWorldImporters_UserData.ndf. (Op, anda menangkap saya meletakkan fail pada pemacu sistem! Tidak! Ia memalukan).

1.3) Dapatkan nama objek daripada DBCC PAGE

Kami kini tahu bahawa halaman #70133 dalam fail data 3 adalah milik pangkalan data WorldWideImporters. Kita boleh melihat kandungan halaman ini menggunakan DBCC PAGE tanpa dokumen dan bendera surih 3604.
Nota: Saya lebih suka menggunakan DBCC PAGE pada salinan yang dipulihkan di suatu tempat pada pelayan lain, kerana ia adalah bahan tanpa dokumen. Dalam beberapa kes, dia boleh mengakibatkan pembuangan sampah (lebih kurang penterjemah - pautan, malangnya, tidak mengarah ke mana-mana, tetapi berdasarkan url, kita bercakap tentang indeks yang ditapis).

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

Dengan menatal ke hasil carian, anda boleh mencari object_id dan index_id.
Menghurai Kunci dan Halaman WaitResource dalam kebuntuan dan kunci
Hampir siap! Kini anda boleh mencari nama jadual dan indeks dengan pertanyaan:

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

Dan di sini kita melihat bahawa penantian pada kunci adalah pada indeks PK_Sales_OrderLines pada jadual Sales.OrderLines.

Nota: Dalam SQL Server 2014 dan ke atas, nama objek juga boleh didapati menggunakan DMO sys.dm_db_database_page_allocations tanpa dokumen. Tetapi anda perlu menanyakan setiap halaman dalam pangkalan data, yang tidak kelihatan sangat keren untuk pangkalan data yang besar, jadi saya menggunakan DBCC PAGE.

1.4) Adakah mungkin untuk melihat data pada halaman yang disekat?

Nuuu, ya. Tetapi… adakah anda pasti anda benar-benar memerlukannya?
Ia perlahan walaupun di atas meja kecil. Tetapi ia agak menarik, jadi oleh kerana anda telah membaca sejauh ini...mari kita bercakap tentang %%physloc%%!

%%physloc%% ialah sihir tanpa dokumen yang mengembalikan ID fizikal untuk setiap entri. anda boleh gunakan %%physloc%% bersama-sama dengan sys.fn_PhysLocFormatter dalam SQL Server 2008 dan ke atas.

Sekarang setelah kita tahu bahawa kita ingin menyekat halaman dalam Sales.OrderLines, kita boleh melihat semua data dalam jadual ini, yang disimpan dalam fail data #3 pada halaman #70133, dengan pertanyaan berikut:

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

Seperti yang saya katakan, ia perlahan walaupun di atas meja kecil. Saya menambah NOLOCK pada permintaan kerana kami masih tidak mempunyai jaminan bahawa data yang ingin kami lihat adalah sama seperti semasa kunci ditemui - jadi kami boleh melakukan bacaan kotor dengan selamat.
Tetapi, hooray, pertanyaan itu mengembalikan kepada saya 25 baris yang diperjuangkan oleh pertanyaan kami.
Menghurai Kunci dan Halaman WaitResource dalam kebuntuan dan kunci
Cukup mengenai kunci PAGE. Bagaimana jika kita sedang menunggu kunci KUNCI?

2) waitresource="KEY: 6:72057594041991168 (ce52f92a058c)" = Database_Id, HOBT_Id (cincang ajaib yang boleh dinyahsulit dengan %%lockres%% jika anda benar-benar mahu)

Jika pertanyaan anda cuba mengunci masukan indeks dan dikunci sendiri, anda mendapat jenis alamat yang berbeza sama sekali.
Memecahkan "6:72057594041991168 (ce52f92a058c)" kepada beberapa bahagian, kita dapat:

  • id_pangkalan data = 6
  • hobt_id = 72057594041991168
  • cincang ajaib = (ce52f92a058c)

2.1) Nyahsulit pangkalan data_id

Ia berfungsi sama seperti contoh di atas! Kami mencari nama pangkalan data menggunakan pertanyaan:

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

Dalam kes saya, ia adalah sama DB WideWorldImporters.

2.2) Nyahsulit hobt_id

Dalam konteks pangkalan data yang ditemui, anda perlu menanyakan sys.partitions dengan beberapa gabungan yang akan membantu menentukan nama jadual dan indeks ...

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

Ia memberitahu saya bahawa permintaan sedang menunggu pada kunci Application.Countries menggunakan indeks PK_Application_Countries.

2.3) Sekarang untuk beberapa %%lockres%% sihir - jika anda ingin mengetahui entri yang telah dikunci

Jika saya benar-benar ingin tahu di baris mana kunci itu diperlukan, saya boleh mengetahui dengan menanyakan jadual itu sendiri. Kita boleh menggunakan fungsi %%lockres%% tanpa dokumen untuk mencari entri yang sepadan dengan cincang ajaib.
Ambil perhatian bahawa pertanyaan ini akan mengimbas keseluruhan jadual, dan pada jadual besar ini mungkin tidak menyeronokkan sama sekali:

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

Saya menambah NOLOCK (atas nasihat Klaus Aschenbrenner di twitter) kerana kunci boleh menjadi masalah. Kami hanya mahu melihat apa yang ada sekarang, dan bukannya apa yang ada semasa urus niaga bermula - Saya tidak fikir konsistensi data penting kepada kami.
Voila, rekod yang kita perjuangkan!
Menghurai Kunci dan Halaman WaitResource dalam kebuntuan dan kunci

Ucapan terima kasih dan bacaan lanjut

Saya tidak ingat siapa yang pertama kali menerangkan banyak perkara ini, tetapi berikut ialah dua siaran tentang perkara yang paling kurang didokumentasikan yang mungkin anda suka:

Sumber: www.habr.com

Tambah komen