围绕单个陈述的交易是做什么的?

Mat*_*tin 67 sql sql-server transactions

我理解一个事务如何对协调一对更新有用.我不明白的是在交易中包装单个陈述,这是我所见过的90%.实际上,在我的经验中,在我的经验中更常见的是找到一系列逻辑相关的事务,每个事务都包含在它们自己的事务中,但整个事务并没有包含在事务中.

在MS-SQL中,在事务中包装单个选择,单个更新,单个插入还是单个删除有什么好处吗?

我怀疑这是迷信编程.

Cha*_*ana 62

它什么都不做.所有单独的SQL语句(除了极少数例外,如无日志的批量插入或截断表)都是自动"在事务中",无论您是否明确说出来......(即使它们插入,更新或删除数百万行) .

编辑:基于@ Phillip在下面的评论...在当前版本的SQL Server中,Even Bulk Inserts和Truncate Table会将一些数据写入事务日志,尽管没有其他操作那么多.与事务角度的关键区别在于,在这些其他类型的操作中,正在修改的数据库表中的数据不在日志中,而是处于允许回滚的状态.

所有这些意味着语句对数据库中的数据所做的更改将记录到事务日志中,以便在操作失败时撤消它们.

"Begin Transaction","Commit Transaction"和"RollBack Transaction"命令提供的唯一功能是允许您将两个或多个单独的SQL语句放入同一事务中.

编辑:(以加强标记评论......)是的,这可能归因于"迷信"编程,或者它可能表明对数据库事务性质的基本误解.一个更慈善的解释是,它只是过度应用一致性的结果,这是不恰当的,而艾默生委婉语的另一个例子是:

一个愚蠢的一致性是小脑袋的大人物,
由小政治家,哲学家和神职人员崇拜

  • 你应该肯定,是的,这是迷信编程.=) (4认同)

Phi*_*ley 9

正如查尔斯布雷塔纳所说,"它什么都不做" - 除了已经完成的任何事情之外什么都没有.

曾经听说过关系数据库的"ACID"要求吗?"A"代表Atomic,意味着该语句可以完整地工作,也可以不工作 - 并且在执行语句时,不会对受该查询影响的数据进行其他查询. BEGIN TRANSACTION/COMMIT将此锁定功能"扩展"为多个语句完成的工作,但它不会对单个语句添加任何内容.

但是,数据库事务日志始终写入修改数据库(插入,更新,删除)时.这不是一种选择,这一事实往往会刺激人们.是的,批量插入和恢复模式很奇怪,但仍然可以写入.

我也会在这里命名 - 降低隔离级别.使用它会影响单个命令,但这样做仍然不会使声明事务包装的查询执行与"独立"查询不同的任何操作.(请注意,他们是非常强大,非常dangeroug多语句声明的交易.)另请注意,"NOLOCK"并不能适用于插入/更新/删除-这些行为总是需要锁.

  • 但是,在没有代码显式事务的情况下在单个命令中执行的两个独立查询将作为数据库中的两个隐式事务执行,这意味着隔离级别和脏/写入数据。 (2认同)

GWR*_*GWR 6

对我来说,将单个语句包装在事务中意味着如果我在执行手动一次性 UPDATE 语句时忘记了 WHERE 子句,我可以将其回滚。它救了我好几次。

例如

--------------------------------------------------------------
CREATE TABLE T1(CPK INT IDENTITY(1,1) NOT NULL, Col1 int, Col2 char(3));
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');

SELECT * FROM T1


--------------------------------------------------------------
/* MISTAKE SCENARIO     (run each row individually) */
--------------------------------------------------------------
BEGIN TRAN YOUR_TRANS_NAME_1;   /* open a trans named YOUR_TRANS_NAME_1 */
    UPDATE T1 SET COL2 = NULL;  /* run some update statement */
    SELECT * FROM T1;       /* OOPS ... forgot the where clause */
ROLLBACK TRAN YOUR_TRANS_NAME_1;    /* since it did bad things, roll it back */
    SELECT * FROM T1;       /* tans rolled back, data restored. */



--------------------------------------------------------------
/* NO MISTAKES SCENARIO (run each row individually) */
--------------------------------------------------------------

BEGIN TRAN YOUR_TRANS_NAME_2;
    UPDATE T1 SET COL2 = 'CBA' WHERE CPK = 4;   /* run some update statement */
    SELECT * FROM T1;               /* did it correctly this time */

COMMIT TRAN YOUR_TRANS_NAME_2           /* commit (close) the trans */

--------------------------------------------------------------

DROP TABLE T1

--------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

  • 也许我的问题没说清楚。我指的是这样的代码:begin tran; 更新 foo 设置 col1 = null; 提交事务;它作为单个批次执行。这是我维护的多个代码库中非常常见的模式,并且在跟踪现有应用程序发出的 sql 时也很常见。您正在描述一个通过两个离散步骤完成的交互过程。 (6认同)