Я розробляв T-SQL протягом декількох років і постійно копаюсь далі, продовжуючи вивчати все, що можу, про всі аспекти мови. Нещодавно я почав працювати в новій компанії і отримав те, що, на мою думку, є дивною пропозицією щодо транзакцій. Ніколи не використовуйте їх. Натомість використовуйте обхідне рішення, яке імітує транзакцію. Це відбувається від нашої DBA, яка працює в одній базі даних з великою кількістю транзакцій, а згодом і багато блокує. База даних, в якій я в основному працюю, не страждає від цього питання, і я бачу, що транзакції використовувалися в минулому.
Я розумію, що блокування очікується при транзакціях, оскільки це за своєю суттю, і якщо ви можете піти, не скориставшись жодним способом, зробіть це. Але я маю багато випадків, коли кожне твердження ПОВИНЕН успішно виконати. Якщо один з них не вдається, всі вони повинні не виконати.
Я завжди зберігав сферу моїх транзакцій якомога вужче, завжди використовувався разом із SET XACT_ABORT ON і завжди в межах TRY / CATCH.
Приклад:
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
Ось що вони запропонували мені зробити.
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
Моє запитання до громади таке. Чи має це сенс життєздатне рішення для операцій?
Моя думка, що я знаю про транзакції і що пропонує рішення, - це те, що ні, це не є життєздатним рішенням і вводить багато пунктів провалу.
У запропонованому вирішенні я бачу чотири неявні транзакції, що відбуваються. Дві вставки в спробу, а потім ще дві транзакції для делетів в улові. Він робить "скасування" вставок, але не відкочуючи нічого, тому насправді нічого не відкочується.
Це дуже базовий приклад для демонстрації концепції, яку вони пропонують. Деякі з фактично збережених процедур, які я робив це, роблять їх вичерпно довгими і складними в управлінні, оскільки "відкат" декількох наборів результатів проти двох значень параметрів у цьому прикладі стає досить складним, як ви могли собі уявити. Оскільки "відкат" зараз робиться вручну, можливість щось пропустити, бо справжнє.
Інше питання, яке, на мою думку, існує - це час та розриви з'єднань. Це все-таки повертається назад? Це моє розуміння того, чому слід використовувати SET XACT_ABORT ON, щоб у цих випадках транзакція поверталася назад.
Дякуємо за ваш відгук заздалегідь!