Bu makalemde undocumented komut ve fonksiyonlar yardımıyla SQL Server'da bir tablodaki bir kayıt satırının fiziksel konumunu nasıl bulunacağını ve fiziksel konumdan nasıl okunacağını aktaracağım.
SQL Server veritabanı sisteminde her bir kayıt için kayıtın tutulduğu file_id (dosya numarası), page_id(sayfa numarası) ve slot_id(slot numarası) üçlüsünden oluşan RID(Row ID) bilgisi tutulmaktadır. Bu bilgiye SQL Server 2005 ile birlikte gelen %%lockres%% komutu ile ulaşabiliyorduk. Satırın bulunduğu fiziksel konumu bulmak için bir test veritabanı ve test tablosu oluşturalım:
--Veritabanı Oluşturma
create database test_dbcc
go
use test_dbcc
--Tablo Oluşturma
create table dbo.WebSites
(id int identity(1,1),
webadress varchar(64),
siteowner varchar(32))
insert into dbo.WebSites(webadress,siteowner) values('www.mehmetguzel.net','Mehmet Güzel')
insert into dbo.WebSites(webadress,siteowner) values('www.mehmetguzel.com','Mehmet Güzel')
insert into dbo.WebSites(webadress,siteowner) values('mehmetguzel.blogspot.com','Mehmet Güzel')
Oluşturduğumuz tablodaki kayıtların fiziksel konumuna bakalım:
select id, webadress, %%lockres%% FileId_PageId_SlotId
from dbo.WebSites
Yukarıdaki resimde; en sağdaki sütun bize ilgili kayıtın bulunduğu file_id, page_id ve slot_id numarasını vermektedir. 1. Satır için file_id 1, page_id 165 ve slot_id 0 değerlerine sahip.
SQL Server 2008 ile birlikte %%lockres%% komutuna benzer işi yapan %%physloc%% komutu geldi. %%physloc%% komutu hex değer döndürür. WebSites tablosundaki kayıtların fiziksel adreslerini hex olarak bulalım:
select id, webadress, %%physloc%% HexAdress
HexAdress kolonun ilk 4 byte’ın kombinasyonu page_id değerini; sonraki 2 byte’ın kombinasyonu file_id değerini; en sondaki 2 byte’ın kombinasyonu ise slot_id değerini verir. Bu değerleri T-SQL ile bulalım:
select cast(convert (binary (4), reverse (substring (%%physloc%%, 1, 4))) as int ) page_id
,cast(convert (binary (2), reverse (substring (%%physloc%%, 5, 2))) as int) file_id
,cast(convert (binary (2), reverse (substring (%%physloc%%, 7, 2))) as int) slot_id
%%physloc%% komutunun döndürdüğü hex değeri kolayca okuyabilmek için undocumented olan sys.fn_PhysLocFormatter() fonksiyonu da kullanılabilir:
select id,webadress, %%physloc%% HexAdress, sys.fn_PhysLocFormatter(%%physloc%%) Adress
%%physloc%% komutunun döndürdüğü hex değerini okuyabileceğimiz undocumented bir diğer fonksiyonumuz sys.fn_physloccracker() fonksiyonudur. Aynı sorguyu sys.fn_physloccracker() fonksiyonunu kullanarak fiziksel adres bilgilerini bulalım:
select w.id, w.webadress, %%lockres%% HexAdress, plc.file_id, plc.page_id, plc.slot_id
from dbo.WebSites w
cross apply sys.fn_physloccracker(%%physloc%%) plc
Data Page yapısını okumak için dbcc page komutu kullanılır. Syntax: dbcc page( {dbid|dbname}, pagenum [,print option] [,cache] [,logical] ) Parametreler: Dbid|dbname : Veritabanı Id yada Veritabanı Adı Pagenum : Page numarası Print option : 0, 1, 2 veya 3 değerini alabilen içerik detayını görüntüleme seçenekleridir. 0 - (Default) : Sadece page header bilgisi için 1 – Page Header ile birlikte her satırın hex bilgisi için 2 – Page Header ve Page seviyesinde detay bilgi için 3 – Page Header ve satır seviyesinde detay bilgi için
Data Page yapısını okumak için dbcc page komutu kullanılır.
Syntax:
dbcc page( {dbid|dbname}, pagenum [,print option] [,cache] [,logical] )
Parametreler:
Dbid|dbname : Veritabanı Id yada Veritabanı Adı
Pagenum : Page numarası
Print option : 0, 1, 2 veya 3 değerini alabilen içerik detayını görüntüleme seçenekleridir.
0 - (Default) : Sadece page header bilgisi için
1 – Page Header ile birlikte her satırın hex bilgisi için
2 – Page Header ve Page seviyesinde detay bilgi için
3 – Page Header ve satır seviyesinde detay bilgi için
Şimdi ise WebSites tablosunda id numarası 1 olan kayıtın fiziksel adresini bulup ilgili page içeriğine page header ve satır seviyesinde detaylı olarak bakalım:
declare @dbccpage varchar(128)
select @dbccpage = 'dbcc page(' + db_name() + ',' + cast(file_id as varchar) + ',' + cast(page_id as varchar) + ',3)'
cross apply sys.fn_physloccracker(%%physloc%%)
where id =1
dbcc traceon(3604)
exec (@dbccpage)
dbcc traceoff(3604)
Sorgu sonucu:
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
PAGE: (1:165)
BUFFER:
BUF @0x05B227D0
bpage = 0x09334000 bhash = 0x00000000 bpageno = (1:165)
bdbid = 8 breferences = 1 bcputicks = 0
bsampleCount = 0 bUse1 = 55342 bstat = 0x9
blog = 0x1c9a bnext = 0x00000000
PAGE HEADER:
Page @0x09334000
m_pageId = (1:165) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8200
m_objId (AllocUnitId.idObj) = 85 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594043498496
Metadata: PartitionId = 72057594039107584 Metadata: IndexId = 0
Metadata: ObjectId = 261575970 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 8 m_slotCnt = 3 m_freeCnt = 7941
m_freeData = 297 m_reservedCnt = 0 m_lsn = (33:210:2)
m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = -1585932016 DB Frag ID = 1
Allocation Status
GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED
PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED
Slot 0 Offset 0x60 Length 48
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 48
Memory Dump @0x1138A060
00000000: 30000800 01000000 03000002 00240030 00777777 0............$.0.www
00000014: 2e6d6568 6d657467 757a656c 2e6e6574 4d65686d .mehmetguzel.netMehm
00000028: 65742047 fc7a656c et Güzel
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4
id = 1
Slot 0 Column 2 Offset 0x11 Length 19 Length (physical) 19
webadress = www.mehmetguzel.net
Slot 0 Column 3 Offset 0x24 Length 12 Length (physical) 12
siteowner = Mehmet Güzel
Slot 1 Offset 0x90 Length 48
Memory Dump @0x1138A090
00000000: 30000800 02000000 03000002 00240030 00777777 0............$.0.www
00000014: 2e6d6568 6d657467 757a656c 2e636f6d 4d65686d .mehmetguzel.comMehm
Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4
id = 2
Slot 1 Column 2 Offset 0x11 Length 19 Length (physical) 19
webadress = www.mehmetguzel.com
Slot 1 Column 3 Offset 0x24 Length 12 Length (physical) 12
Slot 2 Offset 0xf4 Length 53
Record Size = 53
Memory Dump @0x1138A0F4
00000000: 30000800 03000000 03000002 00290035 006d6568 0............).5.meh
00000014: 6d657467 757a656c 2e626c6f 6773706f 742e636f metguzel.blogspot.co
00000028: 6d4d6568 6d657420 47fc7a65 6c mMehmet Güzel
Slot 2 Column 1 Offset 0x4 Length 4 Length (physical) 4
id = 3
Slot 2 Column 2 Offset 0x11 Length 24 Length (physical) 24
webadress = mehmetguzel.blogspot.com
Slot 2 Column 3 Offset 0x29 Length 12 Length (physical) 12
Bu makalemde undocumented komut ve fonsiyonlar yardımıyla SQL Server’da bir kayıt satırının fiziksel page yapısını nasıl okuyacağımıza değindim. Bir sonraki makalede görüşmek dileğiyle.
Not: Makalede kullanılan SQL kodlar SQL Server 2012 RCO sürümünde yazılıp test edilmiştir.
Patris_70 edited Revision 1. Comment: added tr-TR title