the Update语句上的等待,直到交易较早开始提交
交易开始提交提交后立即犯下并发误差
begin isolation level serializable;
update users set first_name = 'aa' where first_name = 'a';
commit;
-- Concurrently, note it operates on last_name instead
begin isolation level serializable;
update users set last_name = 'aa' where last_name = 'a';
commit;
postgresql的可序列隔离级别使用谓词锁定和一种称为可序列化快照隔离(SSI)的技术,该技术旨在
漏和预防异常,而不仅仅是使用行锁。
为什么这是发生的?
eve,尽管这两个交易更新了不同的列(
last_name
),但他们仍在修改同一行。 postgresqltracks读取/写依赖项确保数据库的最终状态可序列化,这意味着结果必须是按照某种序列顺序执行的。
在
postgresql跟踪
利用冲突
使用siread锁
(谓词锁)和write-write依赖项.。 如果两项交易在
SAMEROW上进行,则PostgreSQLcannot保证序列化性
为什么它会发生冲突?
transaction 1(T1
)启动
first_name
'a'
。
读和写入行,将其标记为其序列化集的一部分。
'aa'
T2
last_name
也读和写同一行,即使列不同。
当提交时,PostgreSQL检查是否在
'a'
具有serialization依赖性后开始的任何事务,
'aa'
T1
取决于同一行,后Ql检测一个可能导致不可序列结果的危险周期。
T1
被迫流产,错误:
T2
为什么postgresql允许这两个交易?T2
postgresql通过可序列化快照隔离(SSI)实现可序列化的,该快照
可防止使用依赖关系跟踪的异常。列级写作不是单独跟踪的
eption1:使用可重复的读取
如果您严格不需要序列化,则可以使用可重复的读取隔离:
ERROR: could not serialize access due to read/write dependencies among transactions HINT: The transaction might succeed if retried.
users
prvents丢失了更新和不可重复的读数,但确实可以强制执行完整的序列化。
这种避免不必要的中断,同时仍提供强大的孤立水平 eption2:在开始第二次
之前提交第一笔交易 同时运行它们的目的是手动将它们进行序列化:BEGIN ISOLATION LEVEL REPEATABLE READ; UPDATE users SET first_name = 'aa' WHERE first_name = 'a'; COMMIT;
由于他们没有同时运行,没有发生序列化冲突。
发生冲突是不是因为全行锁,而是因为Postgresql的可以帮助避免此问题。