You're right: at the standard isolation level, read committed
, wrapping select statements in a transaction does not provide any benefits. A group of select statements will be protected from dirty reads whether you wrap them in a transaction or not.
transaction 1 transaction 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
Neither select statement will read the updated user name: it doesn't matter that they are not wrapped in a transaction. For the second class of isolation problems, repeatable read, wrapping selects in a transaction also doesn't provide any benefits:
transaction 1 transaction 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
The begin
and commit
statements won't help here: the second select
will still read the new name.
However, if you run at a higher isolation level, like serializable
or repeatable read
, the group will be protected from non-repeatable reads:
transaction 1 transaction 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
In this scenario, the update
will block until the first transaction is complete.
Higher isolation levels are rarely used because they lower the number of people that can work in the database at the same time. At the highest level, serializable
, a reporting query halts any update activity.