Birkaç yıldan beri T-SQL geliştiriyorum ve her zaman daha fazla kazıyorum, dilin tüm yönleriyle ilgili elimden geldiğince öğrenmeye devam ediyorum. Geçenlerde yeni bir şirkette çalışmaya başladım ve işlemler hakkında garip bir öneri olduğunu düşündüğüm şeyi aldım. Onları asla kullanma. Bunun yerine, bir işlemi simüle eden bir geçici çözüm kullanın. Bu, bir çok işlem ve ardından çok fazla engelleme olan tek bir veritabanında çalışan DBA'mızdan geliyor. Öncelikle çalıştığım veritabanı bu sorundan muzdarip değil ve geçmişte işlemlerin kullanıldığını görüyorum.
Yapmayı engellemenin, doğası gereği olduğu gibi işlemlerle yapılmasının beklendiğini ve birini kullanmadan kurtulabiliyorsanız, elbette bunu yapın. Ancak her ifadenin başarılı bir şekilde yürütülmesi gereken birçok durum var. Biri başarısız olursa hepsinin yerine getirmemesi gerekir.
İşlemlerimin kapsamını her zaman olabildiğince dar, her zaman SET XACT_ABORT ON ile birlikte ve her zaman bir TRY / CATCH içinde kullandım.
Örnek:
CREATE SCHEMA someschema;
GO
CREATE TABLE someschema.tableA
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColA VARCHAR(10) NOT NULL
);
GO
CREATE TABLE someschema.tableB
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColB VARCHAR(10) NOT NULL
);
GO
CREATE PROCEDURE someschema.ProcedureName @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
--Implement error
SELECT 1/0
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@trancount > 0
BEGIN
ROLLBACK TRANSACTION;
END;
THROW;
RETURN;
END CATCH;
END;
GO
İşte benim yapmamı önerdikleri şey.
GO
CREATE PROCEDURE someschema.ProcedureNameNoTransaction @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT ON;
BEGIN
BEGIN TRY
DECLARE @tableAid INT;
DECLARE @tableBid INT;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
SET @tableAid = SCOPE_IDENTITY();
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
SET @tableBid = SCOPE_IDENTITY();
--Implement error
SELECT 1/0
END TRY
BEGIN CATCH
DELETE FROM someschema.tableA
WHERE id = @tableAid;
DELETE FROM someschema.tableB
WHERE id = @tableBid;
THROW;
RETURN;
END CATCH;
END;
GO
Topluma olan sorum şu şekilde. Bu, işlemler için uygun bir geçici çözüm olarak mantıklı geliyor mu?
İşlemler hakkında bildiklerimden ve çözümün önerdiği şeyden kanaatim, hayır, bu uygulanabilir bir çözüm değil ve birçok başarısızlık noktası ortaya koyuyor.
Önerilen geçici çözümde, gerçekleşen dört örtük işlem görüyorum. Iki denemede ekler ve sonra catch içindeki silmeler için iki işlem daha yapılır. Uçları “geri alır” ama hiçbir şeyi geri almadan bu yüzden hiçbir şey geri alınmaz.
Bu, önerdikleri kavramı göstermek için çok temel bir örnektir. Bunu yapmakta olduğum gerçek saklı prosedürlerden bazıları onları çok uzun ve yönetmeleri zorlaştırıyor çünkü çoklu sonuç kümelerinin “geri alınması” bu örnekte iki parametre değerinin tahmin edebileceğiniz gibi oldukça karmaşık bir hal alıyor. "Geri alma" şu anda manuel olarak yapıldığından, gerçek bir şeyleri kaçırmak için fırsat.
Var olduğunu düşündüğüm bir diğer konu zaman aşımları veya kopmuş bağlantılar. Bu hala geri alınıyor mu? Bu, SET XACT_ABORT ON'un neden kullanılması gerektiğine dair bir anlayış, bu durumlarda işlem geri alınacak.
Geri bildiriminiz için şimdiden teşekkür ederiz!