文档说,“可序列化”事务一个接一个地执行。
但实际情况似乎并不是这样。这里有两个几乎相同的事务,唯一的区别是延迟了15秒钟。
#1:
set transaction isolation level serializable
go
begin transaction
if not exists (select * from articles where title like 'qwe')
begin
waitfor delay '00:00:15'
insert into articles (title) values ('qwe')
end
commit transaction go
set transaction isolation level serializable
go
begin transaction
if not exists (select * from articles where title like 'qwe')
begin
insert into articles (title) values ('asd')
end
commit transaction go
第二个事务在第一个事务启动后几秒钟运行。
结果是死锁。第一个事务失败并结束。
Transaction (Process ID 58) was deadlocked on
lock resources with another process and has been chosen as the deadlock victim.
Rerun the transaction.
结论是,可序列化的事务并不是串行的?
serializable
意味着一次只能进行一个事务?据我所知,可序列化的事务隔离级别将在资源上获得独占/范围锁,即使它仅读取数据(在较不严格的隔离级别中,当仅读取数据时,它会获得共享锁),并防止其他用户甚至读取数据。 - M.AliSerializable
事务的整个目的是尽可能并行运行它们。事务的最终结果将与一个接一个地运行它们的结果相同,因此您得到的承诺是并行执行不会造成任何影响。如果您想在两个事务可以同时运行而不发生冲突的情况下一个接一个地运行,请改用显式锁定。在serializable
隔离级别下,您冒着浪费 CPU 和 RAM 的风险,试图并行执行查询以减少典型延迟。 - Mikko Rantalainen