我从事T-SQL的开发已经有好几年了,并且一直在不断深入研究,继续学习有关该语言各个方面的所有知识。我最近开始在一家新公司工作,收到了我认为关于交易的奇怪建议。永远不要使用它们。而是,使用一种模拟交易的解决方法。这来自于我们的DBA,该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
我对社区的问题如下。这对于交易是可行的解决方法吗?
根据我对事务以及解决方案的了解,我的看法是不,这不是可行的解决方案,并且会引入很多故障点。
在建议的解决方法中,我看到发生了四个隐式事务。在try中插入两个,然后在catch中进行两个删除操作。它会“撤消”插入,但不会回滚任何内容,因此实际上不会回滚任何内容。
这是一个非常基本的示例,可以证明他们所建议的概念。我一直在执行的一些实际存储过程使它们变得冗长且难以管理,因为在本示例中,“回滚”多个结果集和两个参数值变得非常复杂,如您所想。由于“回滚”现在是手动完成的,因此有机会错过一些真实的事情。
我认为存在的另一个问题是超时或断开连接。这还会回滚吗?这就是我对为什么应使用SET XACT_ABORT ON的理解,以便在这种情况下事务将回滚。
感谢您的提前反馈!