برخی از تکنیک های کنترل خطای SQL تصادفی برای قابلیت اطمینان و یکپارچگی معامله

رسیدگی به خطا بخش مهمی از نوشتن کد SQL است. چه کار با روش های ذخیره شده ، محرک ها یا معاملات ، رسیدگی به خطای مناسب تضمین می کند که عملیات پایگاه داده قابل اعتماد ، حفظ و قادر به دستیابی به موقعیت های غیر منتظره است. در این نوشتن ، من نمونه های بسیار اساسی از رسیدگی به خطای SQL را در کنار هم قرار داده ام ، از جمله سعی کنید … بلوک های صید ، ورود به سیستم ، مدیریت معاملات و همچنین SavePoint ، XACT_ABORT و کدهای بازگشت رویه ذخیره شده.
برای سادگی ، قطعه های کد T-SQL در این نوشتن فقط برای اهداف مصور ارائه شده است و لزوماً بهترین شیوه های کد نویسی را منعکس نمی کند.
1. اصول رسیدگی به خطای SQL
سعی کنید … گرفتن بلوک
Try … Catch Block مکانیسم اصلی برای رسیدگی به خطاها در SQL Server است. این اجازه می دهد تا استثنائات را ضبط کرده و به طور مناسب پاسخ دهید. اگر خطایی در داخل بلوک امتحان رخ دهد ، Catch Block اجرا می شود ، جزئیات خطا را در یک عبارت SELECT بازگرداند. اگر برای متوقف کردن به اجرای نیاز دارید ، باید به جای آن ، به سادگی یک عبارت SELECT را انجام دهید.
begin try
-- your main sql code here
-- your main sql code here
end try
begin catch
select
error_message() as ErrorMessage,
error_number() as ErrorNumber,
error_severity() as ErrorSeverity,
error_state() as ErrorState
end catch
پرتاب و افزایش
RaiseError به شما امکان می دهد پیام های خطای سفارشی را با میزان شدت مشخص ایجاد کنید.
پرتاب برای پرتاب مجدد خطاهای ضبط شده و متوقف کردن اجرای آن استفاده می شود.
نکته این کد نشان دادن منطق شرطی قبل از ایجاد خطایی در SQL Server با استفاده از Raiserror با Try … Catch Error Handling است.
-- example of conditional logic before raising an error
declare @somecondition int = 1 -- this will cause the error to be thrown
begin try
-- conditionally raise an error
if @somecondition = 1 -- if @somecondition <> 1 then error would not be thrown
begin
raiserror('my custom error occurred due to some condition.', 16, 1) -- raise error
end
-- your main sql code here
select 'hello there'
select 'no error occurred'
end try
begin catch
-- capture the error and re-throw it
throw -- re-throw the error
end catch
شکستن مفهوم “Rethrow”
- خطایی در بلوک آزمایش رخ می دهد.
- اگر someCondition = 1 ، عبارت پرتاب در داخل امتحان خطایی ایجاد می کند.
- اعدام بلافاصله به بلوک صید پرش می کند.
- بلوک Catch خطا را ضبط می کند.
- SQL Server به طور خودکار دسترسی به جزئیات خطا (error_message () ، error_number () و غیره) را فراهم می کند.
- فقط رسیدگی به خطا در گرفتن ، به طور خودکار اجرای را متوقف نمی کند ، زیرا در صورت لزوم نیاز به پرورش مجدد دارد.
- با استفاده از Throw In Catch (پرتاب مجدد خطا)
- به جای ورود به خطای یا رسیدگی به آن سکوت ، پرتاب دوباره همان خطا را دوباره افزایش می دهد.
- این اجازه می دهد تا خطا به تماس گیرنده پخش شود (به عنوان مثال ، یک روش یا برنامه ذخیره شده دیگر).
- نیازی به عبور جزئیات خطا به صورت دستی نیست زیرا SQL Server متن خطا را به خاطر می آورد.
چرا “دوباره پرتاب” به جای فقط “پرتاب”؟
- اصطلاح “پرتاب” به طور کلی به افزایش یک خطای جدید اشاره دارد.
- اصطلاح “Rethrow” هنگام رسیدگی به یک خطای موجود استفاده می شود و دوباره آن را مطرح می کنید.
چه موقع از Rethrow استفاده کنیم؟
- وقتی نمی خواهید خطای اصلی را تغییر دهید.
- هنگامی که می خواهید خطای پشته تماس را پخش کند ، انگار که امتحان … گرفتن در آنجا نبود.
- هنگام رسیدگی به خطاها در مراحل ذخیره شده تو در تو یا سناریوهای بازپرداخت معامله.
نسخه جایگزین از کد SQL با استفاده از پرتاب فقط بدون Raiserror
declare @somecondition int = 1 -- this will cause the error to be thrown
begin try
-- conditionally throw an error
if @somecondition = 1 -- if @somecondition <> 1 then the error would not be thrown
begin
throw 50001, 'my custom error occurred due to some condition.', 1
end
-- your main sql code here
select 'hello there'
select 'no error occurred'
end try
begin catch
-- capture the error and re-throw it
throw -- re-throw the error
end catch
تفاوت های کلیدی بین پرتاب و Raiserror
- نحو ساده تر:
- پرتاب 50001 ، “خطای سفارشی من به دلیل برخی شرایط رخ داده است.” ، 1
- نیازی به مشخص کردن شدت (16) مانند Raiserror نیست.
- پرتاب داخلی برای ایجاد مجدد خطاهای:
- پرتاب داخل گرفتن به طور خودکار خطای گرفتار را بدون نیاز به پارامترها دوباره پرتاب می کند.
- Raiserror نیاز به گرفتن و دوباره قیام مجدد خطای اصلی به صورت دستی دارد.
- همیشه از شدت 16+ استفاده می کند:
- با پرتاب ، شدت باید 50000 یا بالاتر باشد که دامنه خطای سفارشی برای SQL Server است.
- Raiserror به شما امکان می دهد میزان شدت کمتری را مشخص کنید.
چه موقع از پرتاب به جای Raiserror استفاده کنیم؟
- هنگامی که به رسیدگی به خطای ساده تر و تمیز تر نیاز دارید.
- وقتی نیازی به قالب بندی پیشرفته ندارید. Raiserror از تعویض پیام با استفاده از متغیرها پشتیبانی می کند.
- هنگام استفاده از بلوک های Try … Catch ، پرتاب روش ارجح برای استثنائات است.
2. مدیریت معاملات و اتمی
با استفاده از Try … گرفتن با معاملات
معاملات در سرور SQL ، اتمی را تضمین می کند ، به این معنی که تمام عملیات در یک معامله یا به عنوان یک گروه موفق می شوند یا به عنوان یک گروه شکست می خورند. در صورت عدم موفقیت هر بخشی از این فرآیند ، سیستم به حالت اصلی خود باز می گردد ، از به روزرسانی های جزئی جلوگیری می کند و از یکپارچگی پایگاه داده اطمینان می دهد.
استفاده از معاملات هنگام اجرای چندین بیانیه SQL که باید به طور کامل کامل شوند یا اصلاً اجرا نشوند ، برای حفظ قوام بسیار مهم است.
معامله اساسی با رسیدگی به خطا
این کد نمونه نشان می دهد که چگونه یک معامله از اتمی اطمینان می دهد. اگر یک شرط خاص برآورده شود ، خطایی پرتاب می شود که باعث می شود معامله به عقب برگردد:
declare @somecondition int = 1 -- this will cause the error to be thrown
begin transaction
begin try
if @somecondition = 1 -- if @somecondition <> 1 then the error would not be thrown
begin
throw 50001, 'my custom error occurred due to some condition.', 1
end
-- sql operations (insert, update, delete, etc.)
commit transaction
end try
begin catch
rollback transaction
throw -- re-throw the error
end catch
اگر هر جمله SQL در داخل بلوک امتحان شکست بخورد ، SQL Server بلافاصله به بلوک Catch می رود. بلوک Catch معامله را به عقب می اندازد و هرگونه تغییر ایجاد شده از زمان معامله را خنثی می کند و از این طریق از بروزرسانی های جزئی جلوگیری می کند.
خطاهای ورود به سیستم در معاملات
اضافه کردن ورود به خطا به بلوک Catch می تواند به ردیابی خرابی و تشخیص موثر مشکلات کمک کند.
begin transaction
begin try
-- some sql operations (insert, update, delete, etc.)
commit transaction
end try
begin catch
rollback transaction
-- log error details to a custom audit table
insert into errorlog (errormessage, errorprocedure, errorline, errortime)
values (ERROR_MESSAGE(), ERROR_PROCEDURE(), ERROR_LINE(), GETDATE())
select ERROR_MESSAGE() as errormessage
end catch
معاملات برای اتمی و هنگام انجام چندین عملیات وابسته SQL ضروری است. Rollback با بازگرداندن تغییرات در صورت عدم موفقیت ، سازگاری داده ها را تضمین می کند و بلوک Catch… امکان خطاهای ورود به سیستم را فراهم می کند و از بروزرسانی های جزئی جلوگیری می کند. این در کلیه عملیاتی که با SQL در تعامل هستند و یکپارچگی داده ها بسیار مهم است ، مهم است.
معاملات از اتمی بودن اطمینان حاصل می کنند ، به این معنی که هنگام انجام چندین عملیات وابسته SQL ، همه آنها باید با هم موفق شوند یا با هم شکست بخورند. Rollback با بازگرداندن تغییرات در صورت عدم موفقیت ، قوام را حفظ می کند و در حالی که امکان ورود به خطا و جلوگیری از بروزرسانی های جزئی را فراهم می کند ، خطاها را به طور مؤثر انجام می دهد. خطاهای ورود به سیستم اطلاعات اشکال زدایی ارزشمندی را ارائه می دهد ، و اطمینان از قابلیت اطمینان بهتر سیستم را فراهم می کند.
معاملات در هر عملیاتی SQL که در آن یکپارچگی داده بسیار مهم است ، ضروری است ، و اطمینان حاصل می کند که تغییرات در پایگاه داده حتی در صورت بروز خرابی ها هماهنگ و قابل اعتماد باقی می ماند.
با استفاده از SavePoint برای بازپرداخت معاملات جزئی
SavePoint اجازه می دهد تا در حالی که دیگران را دست نخورده نگه می دارد ، بخش های خاصی از معامله را برگردانید. در SQL Server ، SavePoint با اجازه دادن به بازپرداختهای جزئی ، کنترل دقیق تر بر معاملات را فراهم می کند. بر خلاف یک معامله کامل برگشت ، که از زمان معامله همه تغییرات را خنثی می کند ، SavePoint امکان بازگشت تنها بخشی از معامله را در حالی که بقیه را دست نخورده نگه می دارد ، امکان پذیر است. این کار هنگام انجام چندین عملیات مفید است که در صورت بروز خطا فقط قسمتهای خاصی باید از بین بروند.
SavePoint می تواند به حفظ عملیات موفق کمک کند ، بنابراین اگر خطایی رخ دهد ، می توانید به جای دور انداختن کل معامله ، به آخرین SavePoint برگردید. این امر می تواند در هنگام رسیدگی به خرابی در یک معامله بزرگ ، کنترل دقیق تری را فراهم کند که می تواند در هنگام برخورد با عملیات وابسته مفید باشد که در آن اقدامات خاصی باید انجام شود حتی اگر یک قدم بعدی از بین برود و به عقب برگردد.
begin transaction
begin try
-- insert new record into the orders table
insert into orders (orderid, customername, orderdate)
values (101, 'John Doe', getdate())
-- define savepoint before inserting a new
-- record into the orderdetails table
save transaction OrderDetailsSavepoint
-- insert new record into the orderdetails table
insert into orderdetails (orderid, productid, quantity)
values (101, 1, 5)
-- simulate an error
throw 50001, 'simulated error occurred after OrderDetails insertion.', 1
commit transaction
end try
begin catch
select 'error. rolling back to OrderDetailsSavepoint savepoint.'
-- rollback only the changes made after the savepoint
rollback transaction OrderDetailsSavepoint
select 'continuing with remaining transaction...'
-- you can still commit other successful operations
commit transaction
end catch
اگر یک معامله به طور کامل به عقب برگردد (معامله کامل برگشت) ، تمام نقاط ذخیره شده در آن نیز دور ریخته می شوند. با استفاده از SavePoint قفل ها تا زمانی که معامله کامل انجام شود یا به طور کامل چرخانده نشود ، قفل را آزاد نمی کند.
با استفاده از XACT_ABORT برای بازگشت خودکار
XACT_ABORT یک تنظیم سطح جلسه (کل معامله) در SQL Server است که در صورت بروز خطای زمان اجرا ، به طور خودکار کل معامله را باز می گرداند. این امر نیاز به رسیدگی به خطای صریح با معامله برگشت را از بین می برد که می تواند به اطمینان از یکپارچگی داده ها با حداقل کد کمک کند. این برای درج های فله ، به روزرسانی های فله و سایر عملیات “دسته ای” بسیار مفید است زیرا از بروزرسانی های جزئی در عملیات دسته ای بزرگ جلوگیری می کند.
XACT_ABORT بازپرداخت کامل در مورد شکست را تضمین می کند. در صورت عدم انجام هرگونه بیانیه در یک معامله ، کل معامله به طور خودکار به عقب برگردانده می شود. شما نیازی به معاملات صریح و صید صید و بازپرداخت با هر معامله ندارید (کاهش خطای دستی را کاهش می دهد).
set xact_abort on -- turn it on
-- do not need to turn off xact_abort
-- because it applies to the current session or batch
-- after the session ends or a new connection is made
-- xact_abort resets to its default state (off).
begin transaction
begin try
-- insert new record into the orders table
insert into orders (orderid, customername, orderdate)
values (102, 'Jane Doe', getdate())
-- simulate an error
insert into orderdetails (orderid, productid, quantity)
values (102, NULL, 5) -- NULL is not allowed for ProductID
commit transaction -- this will not run if an error occurs
end try
begin catch
select 'error. xact_abort automatically rolled back the transaction.'
end catch
3. ورود به سیستم خطا و گزارش
خطاهای ورود به یک جدول
ذخیره جزئیات خطا در جدول ورود به سیستم به عیب یابی و اشکال زدایی کمک می کند.
begin catch
insert into errorlog (errormessage, errornumber, errorseverity, errorstate)
values (ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE())
end catch
این نمی تواند برای عملکرد بهتر پرس و جو و اضافه کردن سایر اطلاعات مربوط به ورود به سیستم مانند Session_User ، App_Name () ، Host_name () و غیره اضافه شود تا کمک کند تا اشکال زدایی آسانتر شود و زمینه بیشتری را اضافه کند. اگر خطا در یک روش ذخیره شده رخ دهد ، اضافه کردن Error_procedure () و error_line () برای اندازه گیری خوب نیز ممکن است مفید باشد.
با استفاده از پارامترهای خروجی برای گزارش خطا
روشهای ذخیره شده می توانند پیام های خطا را از طریق یک پارامتر خروجی برگردانند.
drop procedure if exists dbo.MyProcedure
go
create procedure dbo.MyProcedure @ErrorMessage nvarchar(4000) output
as
begin
begin try
-- sql logic
end try
begin catch
set @errormessage = error_message() -- return the error message to the calling code
end catch
end
go
پایان
استفاده از تکنیک های کنترل خطای SQL ، قابلیت اطمینان و قابلیت حفظ پایگاه داده را تضمین می کند. با استفاده از Try … Catch ، Management Transaction و ورود به یک جدول می تواند به بهبود مقاومت در سیستم کمک کند ، به طور مؤثر موقعیت های غیر منتظره را انجام داده و یکپارچگی سیستم را حفظ کند.