Tugallanish va qulflarda kalit va Page WaitResource-ni shifrlash

Agar siz bloklangan jarayon hisobotidan foydalansangiz yoki vaqti-vaqti bilan SQL Server tomonidan taqdim etilgan blokirovka grafiklarini to'plasangiz, siz quyidagi holatlarga duch kelasiz:

waitresource=“PAGE: 6:3:70133“

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

Ba'zan siz o'rganayotgan gigant XMLda ko'proq ma'lumot bo'ladi (tug'in grafiklarida ob'ekt va indeks nomlarini aniqlashga yordam beradigan resurslar ro'yxati mavjud), lekin har doim ham emas.

Ushbu matn ularni tushunishga yordam beradi.

Bu erda joylashgan barcha ma'lumotlar Internetda turli joylarda joylashgan, u juda tarqatilgan! Men hamma narsani birlashtirmoqchiman - DBCC PAGE dan hobt_id va hujjatsiz %%physloc%% va %%lockres%% funktsiyalarigacha.

Birinchidan, keling, PAGE blokirovkalarida kutish haqida gapiraylik, keyin esa KEY qulflariga o'tamiz.

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

Agar so'rovingiz PAGE blokirovkasida kutilayotgan bo'lsa, SQL Server sizga o'sha sahifa manzilini beradi.

"PAGE: 6:3:70133" ni bo'lib, biz quyidagilarni olamiz:

  • ma'lumotlar bazasi_id = 6
  • data_file_id = 3
  • sahifa_raqami = 70133

1.1) Database_id shifrini ochish

So'rov yordamida ma'lumotlar bazasi nomini topamiz:

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

Bu ommaviy DB WideWorldImporters mening SQL serverimda.

1.2) Ma'lumotlar fayli nomini qidiring - agar sizni qiziqtirsa

Jadval nomini topish uchun keyingi bosqichda data_file_id dan foydalanamiz. Siz shunchaki keyingi bosqichga o'tishingiz mumkin, lekin agar siz fayl nomi bilan qiziqsangiz, uni topilgan ma'lumotlar bazasi kontekstida ushbu so'rovda data_file_id o'rniga so'rovni bajarish orqali topishingiz mumkin:

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

WideWorldImporters ma'lumotlar bazasida bu WWI_UserData deb nomlangan fayl va men uni C:MSSQLDATAWideWorldImporters_UserData.ndf ga tikladim. (Of, siz meni tizim diskiga fayllarni joylashtirayotganimda ushladingiz! Yo‘q! Bu noqulay edi).

1.3) DBCC PAGE dan obyekt nomini oling

Endi biz 70133-ma'lumotlar faylidagi №3 sahifa WorldWideImporters ma'lumotlar bazasiga tegishli ekanligini bilamiz. Biz ushbu sahifa mazmunini hujjatsiz DBCC PAGE va 3604 kuzatuv bayrog'i yordamida ko'rib chiqishimiz mumkin.
Eslatma: Men DBCC PAGE-dan boshqa serverdagi zaxiradan tiklangan nusxada foydalanishni afzal ko'raman, chunki bu hujjatlashtirilmagan narsa. Ba'zi hollarda u dump hosil bo'lishiga olib kelishi mumkin (taxminan. tarjimon - havola, afsuski, hech qaerga olib kelmaydi, lekin url-ga ko'ra, biz filtrlangan indekslar haqida gapiramiz).

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

Natijalarni aylanib chiqsangiz, siz object_id va index_id ni topishingiz mumkin.
Tugallanish va qulflarda kalit va Page WaitResource-ni shifrlash
Deyarli bajarildi! Endi siz so'rov yordamida jadval va indeks nomlarini topishingiz mumkin:

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

Va endi biz qulfni kutish Sales.OrderLines jadvalining PK_Sales_OrderLines indeksida bo'lganini ko'ramiz.

Eslatma: SQL Server 2014 va undan keyingi versiyalarida obyekt nomini hujjatsiz DMO sys.dm_db_database_page_allocations yordamida ham topish mumkin. Lekin siz ma'lumotlar bazasidagi har bir sahifani so'rashingiz kerak, bu katta ma'lumotlar bazalari uchun unchalik ajoyib ko'rinmaydi, shuning uchun men DBCC PAGE dan foydalandim.

1.4) Bloklangan sahifadagi ma'lumotlarni ko'rish mumkinmi?

Xo'sh, ha. Lekin... bu sizga haqiqatan ham kerakligiga ishonchingiz komilmi?
Hatto kichik stollarda ham sekin. Lekin bu juda zo'r, shuning uchun siz hozirgacha o'qiganingizdan beri... keling, %%physloc%% haqida gapiraylik!

%%physloc%% har bir yozuv uchun jismoniy identifikatorni qaytaradigan hujjatsiz sehrli qismdir. foydalanishingiz mumkin SQL Server 2008 va undan yuqori versiyalarida sys.fn_PhysLocFormatter bilan birga %%physloc%%.

Endi biz Sales.OrderLines-da sahifani bloklashni xohlayotganimizni bilganimizdan so'ng, biz ushbu so'rov yordamida №3 sahifadagi №70133 ma'lumotlar faylida saqlangan ushbu jadvaldagi barcha ma'lumotlarni ko'rib chiqishimiz mumkin:

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

Aytganimdek, hatto kichik stollarda ham sekin. Men so‘rovga NOLOCK ni qo‘shdim, chunki biz ko‘rmoqchi bo‘lgan ma’lumotlar qulf aniqlangandagi bilan bir xil ekanligiga hali kafolatimiz yo‘q – shuning uchun biz iflos o‘qishlarni xavfsiz bajarishimiz mumkin.
Ammo, shoshilinch, so'rov menga so'rovimiz kurashgan bir xil 25 qatorni qaytaradi.
Tugallanish va qulflarda kalit va Page WaitResource-ni shifrlash
PAGE qulflari haqida yetarli. Agar biz KEY qulfini kutayotgan bo'lsak-chi?

2) waitresource=“KEY: 6:72057594041991168 (ce52f92a058c)” = Database_Id, HOBT_Id (agar chindan ham xohlasangiz, %%lockres%% yordamida shifrlanishi mumkin boʻlgan sehrli xesh)

Agar so'rovingiz indeksdagi yozuvni blokirovka qilishga urinsa va o'zi qulflansa, siz butunlay boshqa turdagi manzilga ega bo'lasiz.
"6:72057594041991168 (ce52f92a058c)" ni qismlarga bo'lib, biz quyidagilarni olamiz:

  • ma'lumotlar bazasi_id = 6
  • hobt_id = 72057594041991168
  • sehrli xesh = (ce52f92a058c)

2.1) Database_id shifrini ochish

Bu yuqoridagi misol bilan bir xil ishlaydi! So'rov yordamida ma'lumotlar bazasi nomini toping:

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

Mening holatimda u hali ham xuddi shunday DB WideWorldImporters.

2.2) hobt_id shifrini ochish

Topilgan ma'lumotlar bazasi kontekstida siz jadval va indeks nomlarini aniqlashga yordam beradigan juft birikmalar bilan sys.partitions so'rovini bajarishingiz kerak...

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

Bu so'rovni PK_Application_Countries indeksidan foydalangan holda Application.Countries blokirovkasida kutayotganini aytadi.

2.3) Endi bir oz sehrli %%lockres%% - agar siz qaysi yozuv bloklanganligini bilmoqchi bo'lsangiz

Agar men haqiqatan ham qaysi qatorda qulf yoqilganligini bilmoqchi bo'lsam, jadvalning o'zini so'rash orqali bilib olaman. Sehrli xeshga mos keladigan yozuvni topish uchun hujjatsiz %%lockres%% funksiyasidan foydalanishimiz mumkin.
E'tibor bering, bu so'rov butun jadvalni skanerlaydi va katta jadvallarda bu umuman qiziq bo'lmasligi mumkin:

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

Men NOLOCK (Twitterdagi Klaus Aschenbrennerning maslahati bilan) chunki blokirovkalar muammoga aylanishi mumkin. Biz tranzaksiya boshlanganda nima borligini emas, balki hozir nima borligini ko‘rib chiqmoqchimiz – ma’lumotlarning izchilligi biz uchun muhim deb o‘ylamayman.
Voila, biz kurashgan rekord!
Tugallanish va qulflarda kalit va Page WaitResource-ni shifrlash

Minnatdorchilik va qo'shimcha o'qish

Bularning ko'pini kim birinchi bo'lib tasvirlaganini eslay olmayman, lekin bu erda sizga yoqadigan eng kam hujjatlashtirilgan narsalar haqida ikkita xabar bor:

Manba: www.habr.com

a Izoh qo'shish