Sql 围绕单个语句的事务做什么?

Sql 围绕单个语句的事务做什么?,sql,sql-server,transactions,Sql,Sql Server,Transactions,我理解事务对于协调一对更新是多么有用。我不明白的是在事务中包装单个语句,这是我见过的90%。事实上,根据我的经验,在实际代码中,更常见的是发现一系列逻辑相关的事务,每个事务都包装在自己的事务中,但整个事务并没有包装在一个事务中 在MS-SQL中,在事务中包装单个选择、单个更新、单个插入或单个删除是否有任何好处? 我怀疑这是迷信的编程。当您启动显式事务并发出DML时,被语句锁定的资源将保持锁定状态,并且在手动提交或回滚它之前,语句的结果在事务外部不可见 这是你可能需要或不需要的 例如,您可能希望向

我理解事务对于协调一对更新是多么有用。我不明白的是在事务中包装单个语句,这是我见过的90%。事实上,根据我的经验,在实际代码中,更常见的是发现一系列逻辑相关的事务,每个事务都包装在自己的事务中,但整个事务并没有包装在一个事务中

在MS-SQL中,在事务中包装单个选择、单个更新、单个插入或单个删除是否有任何好处?


我怀疑这是迷信的编程。

当您启动显式事务并发出
DML
时,被语句锁定的资源将保持锁定状态,并且在手动提交或回滚它之前,语句的结果在事务外部不可见

这是你可能需要或不需要的

例如,您可能希望向外部世界显示初步结果,同时仍保持对它们的锁定

在这种情况下,您启动另一个事务,在第一个提交之前放置一个锁请求,从而避免竞争条件


隐式事务在
DML
语句完成或失败后立即提交或回滚。

它什么也不做。所有单独的SQL语句(很少有例外,如无日志的大容量插入或Truncate表)都是自动“在事务中”,无论您是否明确表示。。(即使它们插入、更新或删除数百万行)

编辑:根据@Phillip下面的评论。。。在SQL Server的当前版本中,即使是大容量插入和截断表也会将一些数据写入事务日志,尽管不像其他操作那样多。从事务角度来看,关键区别在于,在这些其他类型的操作中,正在修改的数据库表中的数据不在日志中,其状态允许回滚

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

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

编辑:(加强标记注释…)是的,这可能是由于“迷信”编程造成的,也可能是对数据库事务性质的根本误解。一个更宽厚的解释是,这仅仅是过度使用一致性的结果,这是不恰当的,埃默森委婉语的另一个例子:

愚蠢的一致性是小头脑的妖怪,
受到小政治家、哲学家和神学家的崇拜

正如查尔斯·布雷塔纳(Charles Bretana)所说,“它什么都不做”——除了已经做过的事情之外,什么都不做

听说过关系数据库的“ACID”要求吗?“A”代表原子,这意味着要么语句整体工作,要么不工作——在执行语句时,可以对受该查询影响的数据执行其他查询。BEGIN TRANSACTION/COMMIT将此锁定功能“扩展”到由多个语句完成的工作,但它不向单个语句添加任何内容

但是,数据库事务日志在修改(插入、更新、删除)数据库时总是写入。这不是一个选择,一个容易激怒人们的事实。是的,在大容量插入和恢复模式中有wierdness,但它仍然会被写入


我也将在这里命名drop隔离级别。对此大惊小怪将影响单个命令,但这样做仍然不会使声明的事务包装查询与“独立”查询的执行方式有任何不同。(注意,对于多语句声明的事务,“nolock”不适用于INSERT/updates/DELETE——这些操作总是需要锁。

一个可能的借口是,单个语句可能会导致一堆其他SQL通过触发器运行,他们正在保护数据库,以防出现不好的情况,尽管我希望任何数据库管理系统都已经具备了以同样的方式使用隐式事务的常识


我能想到的另一件事是,一些API允许您禁用自动提交,并且代码是为防止有人这样做而编写的。

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

e、 g


SQL Server具有允许关闭会话自动提交的设置。它甚至是某些客户端的默认设置(请参阅)

根据您使用的框架和/或数据库客户机的不同,如果不将每个单独的命令放入其自己的事务中,可能会导致它们全部集中到一个默认事务中。无论当前的自动提交设置如何,在事务中显式地包装它们中的每一个都清楚地声明了意图,并实际确保它按照程序员的预期方式发生,特别是在没有公司范围的自动提交策略的情况下

如果在数据库中观察到begin-tran/commit-tran命令(根据您的评论),也可能是框架代表一个毫无戒心的程序员生成它们。(有多少开发人员仔细检查他们的框架生成的SQL代码?)


我希望这仍然是相关的,尽管这个问题有点古老。

你应该肯定,是的,这是迷信的编程。=)@查尔斯,MySQL怎么样?@Pacerier,我对MySQL不太精通,但如果他们的产品在这方面表现不同,我会大吃一惊
--------------------------------------------------------------
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

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