SET XACT_ABORT ON
Saklı yordamda kullanmanın faydası nedir ?
SET XACT_ABORT ON
Saklı yordamda kullanmanın faydası nedir ?
Yanıtlar:
SET XACT_ABORT ON
SQL Server'a tüm işlemin geri alınmasını ve bir çalışma zamanı hatası oluştuğunda toplu işlemi iptal etmesini bildirir. SQL Server'ın kendisi yerine istemci uygulamasında oluşan bir komut zaman aşımı gibi durumlarda sizi kapsar (varsayılan XACT_ABORT OFF
ayar kapsamında değildir ).
Bir sorgu zaman aşımı işlemi açık bırakacağından, açık işlemlerle SET XACT_ABORT ON
yapılan tüm saklı yordamlarda (başka bir işlem yapmak için özel bir nedeniniz yoksa) açık bir işlemle bağlantı üzerinde çalışma yapan bir uygulamanın sonuçları felaket olduğu için önerilir.
Dan Guzman'ın Blogunda gerçekten harika bir genel bakış var ,
BEGIN TRY
- BEGIN CATCH
ve ROLLBACK
birlikte BEGIN CATCH
Sql bloğun?
BEGIN TRY
- BEGIN CATCH
istemci uygulamasında oluşan bir zaman aşımı gibi şeyleri yakalamaz ve bazı SQL hataları da görünmezdir ve sizi beklemeyeceğiniz açık bir işlem bırakır.
Bence SET XACT_ABORT ON, SQL 2k5'e BEGIN TRY / BEGIN CATCH eklenmesi ile geçersiz kılındı. Transact-SQL'de istisna bloklarından önce hataları işlemek gerçekten zordu ve dengesiz prosedürler çok yaygındı (çıkışta girişe kıyasla farklı bir @@ TRANCOUNT olan prosedürler).
Transact-SQL özel durum işleme eklenmesi ile işlemleri düzgün bir şekilde dengelemek için garanti edilen doğru yordamları yazmak çok daha kolaydır. Örneğin, bu şablonu özel durum işleme ve iç içe işlemler için kullanıyorum :
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
go
Kurtarılabilir hatalar durumunda yalnızca kendi çalışmalarını geri alan atomik prosedürler yazmama izin veriyor.
Transact-SQL yordamlarının karşılaştığı ana sorunlardan biri veri saflığıdır : bazen alınan parametreler veya tablolardaki veriler basit yanlıştır, bu da yinelenen anahtar hataları, referans kısıtlama hataları, kısıtlama hatalarını kontrol eder vb. Sonuçta, bu tam olarak bu kısıtlamaların rolü, eğer bu veri saflığı hataları imkansız ve iş mantığı tarafından yakalansaydı, kısıtlamalar tamamen eski olurdu (etki için dramatik abartı eklendi). XACT_ABORT AÇIK ise, tüm bu hatalar istisnayı zarif bir şekilde işleyen istisna bloklarını kodlayabilmenin aksine tüm işlemin kaybolmasına neden olur. Tipik bir örnek bir INSERT yapmaya ve PK ihlali konusunda bir GÜNCELLEME'ye dönmeye çalışmaktır.
MSDN'den alıntı :
SET XACT_ABORT AÇIK olduğunda, bir Transact-SQL deyimi bir çalışma zamanı hatası verirse, tüm işlem sonlandırılır ve geri alınır. SET XACT_ABORT KAPALI olduğunda, bazı durumlarda yalnızca hatayı yükselten Transact-SQL deyimi geri alınır ve işlem işlemeye devam eder.
Uygulamada bu, bazı ifadelerin başarısız olabileceği ve işlemin 'kısmen tamamlandığı' anlamına gelebileceği ve arayan için bu başarısızlığın bir işareti olmayabileceği anlamına gelir.
Basit bir örnek:
INSERT INTO t1 VALUES (1/0)
INSERT INTO t2 VALUES (1/1)
SELECT 'Everything is fine'
Bu kod, XACT_ABORT OFF ile 'başarıyla' yürütülür ve XACT_ABORT ON ile bir hata ile sonlanır ('INSERT INTO t2' yürütülmez ve istemci uygulaması bir istisna oluşturur).
Daha esnek bir yaklaşım olarak, her ifadeden sonra (eski okul) @@ HATA kontrol edebilir veya TRY ... CATCH bloklarını (MSSQL2005 +) kullanabilirsiniz. Şahsen bazı gelişmiş hata işlemeleri için hiçbir neden olmadığında XACT_ABORT'u AÇIK olarak ayarlamayı tercih ederim.
İstemci zaman aşımları ve bunları işlemek için XACT_ABORT kullanımı ile ilgili olarak, bence SqlClient gibi istemci API'larında zaman aşımına sahip olmanın en az bir iyi nedeni var ve bu, istemci uygulama kodunu SQL sunucu kodunda meydana gelen çıkmazlardan korumaktır. Bu durumda, istemci kodunda hata yoktur, ancak komutun sunucuda tamamlanmasını bekleyen sonsuza kadar kendini engellemekten korumak gerekir. Buna karşılık, istemci kodunu korumak için istemci zaman aşımlarının olması gerekiyorsa, XACT_ABORT ON'un sunucu kodunu istemcinin iptal etmesine karşı korumak zorundaysa, sunucu kodunun yürütülmesi istemcinin beklemek istediğinden daha uzun sürmesi durumunda.