Açar və Səhifə Gözləmə Resursunu kilidlərdə və kilidlərdə deşifrə edin

Əgər siz bloklanmış proses hesabatından istifadə etsəniz və ya vaxtaşırı SQL Server tərəfindən təmin edilən kilidləmə qrafiklərini toplasanız, belə şeylərlə qarşılaşacaqsınız:

waitresource="SƏHİFƏ: 6:3:70133"

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

Bəzən öyrəndiyiniz o nəhəng XML-də daha çox məlumat olacaq (dalan qrafikləri obyektin və indeksin adlarını öyrənməyə kömək edən resursların siyahısını ehtiva edir), lakin həmişə deyil.

Bu mətn onları deşifrə etməyə kömək edəcək.

Burada olan bütün məlumatlar İnternetdə müxtəlif yerlərdə var, sadəcə çox yayılmışdır! Mən DBCC PAGE-dən hobt_id-ə, sənədsiz %%physloc%% və %%lockres%% funksiyalarına qədər hamısını bir yerə yığmaq istəyirəm.

Əvvəlcə PAGE kilidlərində gözləmələrdən danışaq, sonra KEY kilidlərinə keçək.

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

Əgər sorğunuz SƏHİFƏ kilidini gözləyirsə, SQL Server sizə həmin səhifənin ünvanını verəcək.

"SƏHİFƏ: 6:3:70133"-i parçalayaraq əldə edirik:

  • verilənlər bazası_id = 6
  • data_file_id = 3
  • səhifə_nömrəsi = 70133

1.1) verilənlər bazası_id-nin şifrəsini açın

Sorğudan istifadə edərək verilənlər bazasının adını tapın:

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

Bu ictimaidir DB WideWorldImporters SQL Serverimdə.

1.2) Məlumat faylının adını axtarırsınız - maraqlanırsınızsa

Cədvəl adını tapmaq üçün növbəti addımda data_file_id istifadə edəcəyik. Siz sadəcə növbəti addıma keçə bilərsiniz, lakin fayl adı ilə maraqlanırsınızsa, onu tapılan verilənlər bazası kontekstində sorğu işlətməklə, data_file_id-i bu sorğuda əvəz etməklə tapa bilərsiniz:

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

WideWorldImporters verilənlər bazasında bu, WWI_UserData adlı fayldır və mən onu C:MSSQLDATAWideWorldImporters_UserData.ndf olaraq bərpa etmişəm. (Oops, siz məni sistem diskinə faylları yerləşdirərkən tutdunuz! Xeyr! Bu, utancvericidir).

1.3) DBCC SƏHİFƏsindən obyekt adını əldə edin

İndi bilirik ki, məlumat faylı 70133-də #3 səhifə WorldWideImporters verilənlər bazasına aiddir. Biz sənədsiz DBCC SƏHİFƏsindən və 3604 iz bayrağından istifadə edərək bu səhifənin məzmununa baxa bilərik.
Qeyd: Mən DBCC SƏHİFƏni başqa serverdə bərpa edilmiş surətdə istifadə etməyi üstün tuturam, çünki bu sənədləşdirilməmiş materiallardır. Bəzi hallarda o tullantı ilə nəticələnə bilər (təqribən. tərcüməçi - bağlantı, təəssüf ki, heç bir yerə aparmır, lakin url-ə görə, biz süzülmüş indekslərdən danışırıq).

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

Nəticələrə sürüşərək, siz object_id və index_id tapa bilərsiniz.
Açar və Səhifə Gözləmə Resursunu kilidlərdə və kilidlərdə deşifrə edin
Demək olar ki, hazırdır! İndi cədvəl və indeks adlarını sorğu ilə tapa bilərsiniz:

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

Və burada biz kiliddə gözləmənin Sales.OrderLines cədvəlinin PK_Sales_OrderLines indeksində olduğunu görürük.

Qeyd: SQL Server 2014 və daha yuxarı versiyalarda obyektin adını sənədsiz DMO sys.dm_db_database_page_allocations vasitəsilə də tapmaq olar. Amma verilənlər bazasında hər səhifəni sorğulamalısınız, bu, böyük verilənlər bazaları üçün o qədər də gözəl görünmür, ona görə də DBCC PAGE-dən istifadə etdim.

1.4) Bloklanmış səhifədəki məlumatları görmək mümkündürmü?

Nuuu, bəli. Amma... buna həqiqətən ehtiyacınız olduğuna əminsinizmi?
Kiçik masalarda belə yavaş olur. Amma bu, çox gözəldir, ona görə də bura qədər oxuduğunuza görə...gəlin %%physloc%% haqqında danışaq!

%%physloc%% hər bir giriş üçün fiziki identifikator qaytaran sənədsiz sehr parçasıdır. istifadə edə bilərsən SQL Server 2008 və daha yüksək versiyalarda sys.fn_PhysLocFormatter ilə birlikdə %%physloc%%.

Sales.OrderLines-də səhifəni bloklamaq istədiyimizi bildiyimizə görə, 3-cü səhifədəki №70133 məlumat faylında saxlanılan bu cədvəldəki bütün məlumatlara aşağıdakı sorğu ilə baxa bilərik:

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

Dediyim kimi, kiçik masalarda belə yavaş olur. Sorğuya NOLOCK əlavə etdim, çünki baxmaq istədiyimiz məlumatların kilidin aşkar edildiyi vaxtla eyni olduğuna hələ də heç bir zəmanətimiz yoxdur - beləliklə, çirkli oxunuşları təhlükəsiz edə bilərik.
Amma, yaş olsun, sorğu mənə sorğumuzun mübarizə apardığı 25 sıranı qaytarır.
Açar və Səhifə Gözləmə Resursunu kilidlərdə və kilidlərdə deşifrə edin
PAGE kilidləri haqqında kifayətdir. Bəs biz KEY kilidini gözləyiriksə?

2) waitresource="AÇAR: 6:72057594041991168 (ce52f92a058c)" = Database_Id, HOBT_Id (həqiqətən istəsəniz %%lockres%% ilə deşifrə edilə bilən sehrli hash)

Sorğunuz indeks girişini kilidləməyə çalışırsa və öz-özünə kilidlənirsə, siz tamamilə fərqli ünvan növü əldə edirsiniz.
"6:72057594041991168 (ce52f92a058c)"-ni hissələrə ayırsaq, əldə edirik:

  • verilənlər bazası_id = 6
  • hobt_id = 72057594041991168
  • sehrli hash = (ce52f92a058c)

2.1) verilənlər bazası_id-nin şifrəsini açın

Yuxarıdakı nümunə ilə eyni işləyir! Sorğudan istifadə edərək verilənlər bazasının adını tapırıq:

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

Mənim vəziyyətimdə də eynidir DB WideWorldImporters.

2.2) hobt_id şifrəsini açın

Tapılmış verilənlər bazası kontekstində, cədvəlin və indeksin adlarını təyin etməyə kömək edəcək bir neçə birləşmə ilə sys.partitions sorğusu etməlisiniz ...

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 sorğunun PK_Application_Countries indeksindən istifadə edərək Application.Countries kilidində gözlədiyini deyir.

2.3) İndi bəzi %%lockres%% sehr üçün - hansı girişin kilidləndiyini öyrənmək istəyirsinizsə

Əgər həqiqətən də kilidin hansı cərgədə lazım olduğunu bilmək istəsəm, cədvəlin özündən sorğu-sual edərək öyrənə bilərəm. Sehrli hash-ə uyğun gələn girişi tapmaq üçün sənədsiz %%lockres%% funksiyasından istifadə edə bilərik.
Qeyd edək ki, bu sorğu bütün cədvəli skan edəcək və böyük cədvəllərdə bu heç də əyləncəli olmaya bilər:

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

Mən NOLOCK əlavə etdim (Twitter-də Klaus Aschenbrennerin məsləhəti ilə) çünki kilidlər problem ola bilər. Biz sadəcə olaraq, əməliyyat başlayanda orada nə olduğuna deyil, indi nə olduğuna baxmaq istəyirik - məlumatların ardıcıllığının bizim üçün vacib olduğunu düşünmürəm.
Voila, uğrunda mübarizə apardığımız rekord!
Açar və Səhifə Gözləmə Resursunu kilidlərdə və kilidlərdə deşifrə edin

Minnətdarlıq və əlavə oxu

Bu şeylərin çoxunu kimin ilk dəfə təsvir etdiyini xatırlamıram, amma bəyənə biləcəyiniz ən az sənədləşdirilmiş şeylər haqqında iki yazı var:

Mənbə: www.habr.com

Добавить комментарий