5 Kasım 2014 Çarşamba

Rollback hakkında dikkat etmeniz gerekenler

Selam!

"sys.fn_dblog" Table Valued Function (TVF)'ını önceden duymuş muydunuz? Duymadıysanız da hayıflanmayın, çünkü zaten Microsoft tarafından dokümante edilmemiş bir TVF; bununla birlikte en azından benim bugüne kadar öyle veya böyle, orada veya burada sık sık karşılaştığım bir TVF.

Peki ne yapıyor bu adam? O anda bağlı bulunduğunuz veritabanının Transaction Log'undaki aktif kayıtları okuyor. Peki nedir bu aktif kayıtlar? Bunlar, henüz veritabanının veri dosyasına yazılmamış olan (en son yapılan Checkpoint'ten önceki), ama Transaction Log dosyasının içinde bulunan kayıtlardır.

Peki ben neden bu TVF'ten bahsetmek istedim? Size veritabanınızda bir işlem yaptığınızda bunun Transaction Log dosyasına temel olarak nasıl işlendiğini anlatmak istedim. Bununla birlikte en çok dikkat çekmek istediğim konu ise, bir Explicit Transaction başlatıp sonra bunu Rollback yaptığınızda (veya aynı şeyin bir Implicit Transaction'ın başına geldiğinde) neler olduğunu anlatmak istedim.

Örneğin bir tabloya yeni bir kayıt INSERT etmek istediğinizde bu işlemin Transaction Log dosyasına nasıl kaydedildiğini anlatayım. Bunun için test veritabanımda aşağıdaki gibi bir tablo oluşturuyorum:

CREATE TABLE [dbo].[tablom1](
[alan1] [tinyint] NULL
) ON [PRIMARY]
GO

Daha sonra aşağıdaki komut ile bu tabloya bir kayıt giriyorum

INSERT INTO tablom1 VALUES(6)

Daha sonra sys.fn_dblog TVF'ı ile Transaction Log dosyasını sorguluyorum. sys.fn_dblog TVF'ı iki tane parametre alır. Birincisi StartLSN, diğeri de EndLSN. Yani Log Sequence Number (LSN) başlangıcı ve bitişini tanımlayıp sorgulayabiliyorsunuz. LSN, her bir işlem için verilmiş eşsiz bir değerdir, 3 bölümden oluşur, ilgi VLF (Vitual Log File) numarası, ikincisi VLF içerisindeki blok numarası (bir VLF içerisinde birden fazla Transaction bulunabilir), üçüncüsü de işlem sıra numarasıdır.

Not: Transaction Log dosyası kendi içinde de mimari olarak Virtual Log File'lardan oluşur, bunlar da aralarında Active ve Passive olarak ayrılır.

Bu iki parametreyi NULL olarak belirterek de çalıştırabilirsiniz, ki genelde de böyle kullanılır:

SELECT * FROM sys.fn_dblog(NULL, NULL)

Commit Transaction

Eğer yukarıdaki INSERT komutunu çalıştırırsanız (ve sonrasında başka bir işlem yapmazsanız) sys.fn_dblog'u sorguladığınızda hemen yukarıdaki gibi bir sonuçla karşılaşacaksınız. Operation alanındaki değerleri tek tek açıklamak bu yazımın konusunun dışında, ama kırmızı dikdörtgen ile işaretlediğim alan içerisinde (Transaction ID'ye dikkat) işaretlediğim Implicit Transaction işlemini (INSERT işlemi için BEGIN TRAN ile Explicit Transaction oluşturmadık, fakat biz bunu yapmasak da her işlem bir Transaction'dır bu nedenle eğer biz tanımlamazsak bile işlemler Implicit Transaction ile çalıştırılır) açıklamaya çalışayım. LOP_BEGIN_ XACT ile Transaction'ımız başlatılmış olur, bununla LOP_COMMIT_XACT (veya işlem Rollback edildiyse de LOP_ABORT_XACT) arasında kalan işlemler gerçekleştirilmiş olur. Yukarıdaki örnekte LOP_BEGIN_XACT ile Transaction'ımızın başladığını, LOP_INSERT_ROWS ile INSERT işlemimizin gerçekleştiğini ve LOP_COMMIT_XACT ile de işlemimizin Commit edildiğini görebilirsiniz. Yani INSERT işlemimiz için Transaction Log dosyasında 3 adet kayıt oluşturulmuş oldu.

Peki Rollback'te ne oluyor? Hemen bunu da test edelim. Aşağıdaki komutu çalıştırıyorum ve bu şekilde Ornek adında bir Transaction'ı Explicitly oluşturmuş oluyorum. Ardından INSERT işlemimi gerçekleştiriyorum ve sonrasında da Transaction'ımı Rollback etmek için de ROLLBACK TRAN komutunu çalıştırıyorum. Sizce Transaction Log dosyasında kaç tane kayıt oluşmuş olacak?

BEGIN TRAN Ornek
INSERT INTO tablom1 VALUES(6)
INSERT INTO tablom1 VALUES(7)
INSERT INTO tablom1 VALUES(8)
ROLLBACK TRAN Oren

Sonuç aşağıdaki gibi:

SELECT * FROM sys.fn_dblog(NULL, NULL)

Rollback Transaction
Lütfen yine kırmızı dikdörtgen ile işaretlediğim Transaction'a bakın. Yine dikkatinizi Transaction ID'ye çekmek istiyorum öncelikle, 0000:0000075d. Gördüğünüz gibi tüm INSERT ve DELETE işlemleri tek bir Transaction içerisinde gerçekleşiyor ve EVET, doğru görüyorsunuz, her bir INSERT işleminizin Rollback edilmesi için işlem başına bir LOG_DELETE_ROWS işlemi yapılıyor. En son işlem de LOP_ABORT_XACT işlemi.

Belki UPDATE için durumun ne olacağını merak ediyor olabilirsiniz, örneğin 100 kayıtlık bir UPDATE işleminiz Rollback olduğunda ne mi oluyor? Tablomuzda 100 adet kayıt varken aşağıdaki komutu çalıştırdığımızda:

UPDATE tablom1 SET alan1 = 0

ve sys.fn_dblog ile sorguladığımızda Transaction için yapılan kayıt haricinde 100 adet LOP_MODIFY_ROW işlemi görüyoruz. Rollback işleminde de tüm bu kayıtlara yine 100 adet kayıt ekleniyor!

Bu nedenlerle, özellikle uzun süren DML işlemleriniz sonucu siz elle veya kendiliğinden (bir hata sonrası) Rollback işlemi gerçekleştiğinde Transaction Log dosyanızın bulunduğu diskte yeterli derecede boş alan olduğundan emin olmanızda fayda var. Örneğin çok büyük bir işlem gerçekleştirdiniz diyelim ve bu işlem herhangi bir nedenden dolayı Rollback oldu diyelim ve tüm bunların neticesinde de Transaction Log dosyanız doldu ve hatta bulunduğu diski de doldurdu diyelim, ne mi olur? Veritabanınız Suspect duruma düşer! Ve bunun olmasını kesinlikle istemezsiniz. Bu nedenle Rollback işlemlerini özellikle kontrollü bir şekilde yapacağınız zaman bu paylaştığım bilgileri aklınızda tutun, gerekli önlemleri alın, özellikle Transaction Log dosyanızın doluluk oranını, disk doluluk oranlarını iyi ve güvenli bir şekilde takip ettiğinizden emin olun.

Sevgiler,
Ekrem Önsoy


Hiç yorum yok: