在事务中包含select语句有什么意义?

Jus*_*ner 29 t-sql transactions sql-server-2005

在事务中包含select语句有什么意义?我认为select语句只是来自数据库的"GET"数据,它们没有机会回滚一些东西,因为你无法改变数据.那么,这是否说我们永远不需要在事务中放置select语句?我对吗?

谢谢.

And*_*mar 32

你说的没错:在标准的隔离级别,read committed你不需要包装在交易select语句.无论是否将它们包装在事务中,Select语句都将受到保护,不会被脏读.

connection 1:                          connection 2:

                                       begin transaction
                                       update user set name = 'Bill' where id = 1
select name from users where id = 1
                                       rollback transaction
Run Code Online (Sandbox Code Playgroud)

select语句不会读取回滚更新:它们没有包含在事务中并不重要.

如果您需要可重复读取,则在默认事务中包装选择无效:

connection 1:                          connection 2:

begin transaction
select name from users where id = 1
                                       update user set name = 'Bill' where id = 1
select name from users where id = 1
commit transaction
Run Code Online (Sandbox Code Playgroud)

begincommit语句将不会在这里帮助:第二select 可以读取旧的名称,或者它可以读取新的名称.

但是,如果您以更高的隔离级别运行,例如serializablerepeatable read,则将保护该组免受不可重复的读取:

connection 1:                          connection 2:

set transaction isolation level
    repeatable read
begin transaction
select name from users where id = 1
                                       update user set name = 'Bill' where id = 1
select name from users where id = 1              |
commit transaction                               |
                                                 |--> executed here
Run Code Online (Sandbox Code Playgroud)

在这种情况下,update将阻止直到第一个事务完成.

很少使用较高的隔离级别,因为它们会同时降低可在数据库中工作的人数.在最高级别,serializable报告查询会暂停所有更新活动.


kro*_*ock 7

您可能在此交易期间正在进行其他更新/插入.如果访问数据库的代码是以可重用的方式编写的,那么您可能不会选择是否是事务中发生的唯一事情.

您的select语句可能希望在事务持续期间保持一致,并且与其他事务中发生的数据更改保持一致.您需要在系统中设置某种隔离级别,以防止脏读(读取另一个事务中未提交的更改)或幻像读取(读取另一个事务中的已提交更改).

不用说,使用交易可以更好地满足您的需求.


dkr*_*etz 5

单个SELECT语句是开始时的原子 - 将它封装在事务中是多余的.如果有多个SELECT语句,则保证在完成所有SELECT语句之前,没有人更改任何影响它们的任何内容.