ProHoster > Blog > Pentadbiran > Menghurai Kunci dan Halaman WaitResource dalam kebuntuan dan kunci
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:
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
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.
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%%!
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.
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 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!
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: