在事务中附加select语句有什么意义?我认为select语句只是来自数据库的“GET”数据,他们没有机会回滚一些东西,因为你无法改变数据。那么,这是否说我们永远不需要在事务中放置select语句?我是对的吗?
感谢。
答案 0 :(得分:32)
你是对的:在标准isolation level,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
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
begin
和commit
语句在这里没有帮助:第二个select
可能读取旧名称,或可能> strong>阅读新名称。
但是,如果您运行的隔离级别较高,例如serializable
或repeatable 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
,报告查询会暂停所有更新活动。
答案 1 :(得分:7)
您可能在此交易期间正在进行其他更新/插入。如果访问数据库的代码是以可重用的方式编写的,那么您可能不会选择是否是事务中发生的唯一事情。
您的select语句可能希望在事务持续期间保持一致,并且与其他事务中发生的数据更改保持一致。您需要在系统中设置某种isolation level以防止脏读(读取另一个事务中未提交的更改)或幻像读取(读取另一个事务中的已提交更改)。
毋庸置疑,通过使用交易,您将获得更好的服务。
答案 2 :(得分:5)
单个SELECT语句以原子为开头 - 将其封闭在事务中是多余的。如果有多个SELECT语句,则保证在完成所有SELECT语句之前,没有人更改任何影响它们的任何内容。
答案 3 :(得分:3)
没有
事务为您提供了一致的数据库视图。
如果您希望选择在重复时返回相同的结果,则事务可以提供该结果。
答案 4 :(得分:3)
您可能没有更改数据,但可能还有其他一些数据库连接。
答案 5 :(得分:2)
使用带有选择的交易的另一个原因:
在某些时候,您可能希望从参与事务的其他方法调用select方法,并且您希望select参与当前事务。如果您具有一致的设计,其中所有数据库操作都在事务中执行,则任何方法的调用者都知道它将参与其事务。
对于较小的前期开发成本,这可以帮助避免一些相当大的更改,以后尝试在if / when需求更改或添加新需求时进行交易。
答案 6 :(得分:0)
如果您确定所发生的一切都是SELECT,那么它不需要在事务中。你是否100%确定现在和永远更多它只是一个SELECT?