2010-06-23 95 views
26

在事务中包含select语句有什么意义?我认为select语句只是数据库中的“GET”数据,他们没有机会回滚某些内容,因为你无法更改数据。那么,这是否说我们从不需要在交易中放置选择语句?我对吗?在事务中包含select语句有什么意义?

谢谢。

回答

31

您是对的:在标准isolation levelread 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 

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

如果需要repeatable reads,在默认的事务,然后选择包装没有帮助:

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 

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 

在这种情况下,update将阻塞,直到第一个事务做完了。

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

+0

关于您的最后一段,**为什么更新块会被阻止?**是不是可能更新仍然没有阻塞,但是第一个事务是可重复读取的,仍然会继续使用旧值? – Pacerier 2014-12-30 04:48:02

+0

@Pacerier:可重复读取表示如果您读取两次,第二次读取将返回相同的结果。与Oracle或PostgeSQL不同,SQL Server不保留旧值。您可以使用['SET READ_COMMITTED_SNAPSHOT ON'](http://msdn.microsoft.com/zh-cn/library/ms345124.aspx)更改此行为。 – Andomar 2014-12-31 00:25:05

+0

嗯,这很奇怪,似乎是MySQL的默认值。因此,对于SQL服务器,运行'set read_committed_snapshot on'后,说“更新”将不再**阻止是正确的吗? – Pacerier 2015-01-03 11:23:27

7

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

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

不用说,通过使用交易你会更好地服务。

4

事务让你的数据库的一致视图。

如果您希望您的选择在重复它们时返回相同的结果,则事务可以提供该结果。

4

可能不会更改数据,但可能会有其他数据库连接。

1

如果您确定发生的所有事情都是SELECT,那么它不需要处于事务中。你是否100%肯定现在和永远更多它将只是一个SELECT?

5

一个单一的SELECT语句是以原子开始的 - 将它包含在一个事务中是多余的。如果有多个SELECT语句,则保证没有人改变任何影响它们的任何内容,直到它们全部完成。

2

另一个原因是使用交易与选择:

有可能在某些时候,你可能希望从那些参与交易的其他方法调用你的选择方法,你想选择参加当前事务。如果您有一个一致的设计,即在事务中执行所有数据库操作,则任何方法的调用者都知道它将参与其事务。

对于小的前期开发成本,这可能有助于避免稍后尝试在需求更改或添加新要求时试图阻碍交易的一些相当大的更改。

相关问题