我正在使用应用程序互斥锁和SERIALIZABLE
.
我认为这会使这些操作尽可能地酸,但现在我担心读取可能会因为锁定而导致那些写入事务失败。
读取在 libpqxx 准备好的语句事务中。我已经阅读了docs、wiki和white paper,但我无法找到如何配置读取事务,以便它永远不会冒另一个关键的可序列化写入事务失败的风险。
我无法确定锁是否会导致序列化失败。他们可以吗?
读取不需要非常酸,因为应用程序会补偿竞争条件、旧数据等。主要关注的是可序列化的关键写入事务不会因其他读取而失败。
只读准备语句应该如何配置才能绝对不冒另一个可序列化事务写入失败的风险?
READ ONLY
事务不能导致写事务(不执行 DDL)失败,除非它显式使用或LOCK TABLE
咨询锁。READ ONLY
交易不能SELECT ... FOR SHARE
或SELECT ... FOR UPDATE
。由于他们不能做 DML,他们可以对表采取的最强锁是ACCESS SHARE
,它只与ACCESS EXCLUSIVE
DDL 采取的锁冲突。如果写入事务是 ,则只读事务也不会导致序列化失败
SERIALIZABLE
,因为序列化失败需要两个事务都执行写入。总是可以在读/写事务之前或之后对只读事务进行逻辑序列化,因为它们不可能相互依赖。所以:使用
READ COMMITTED
orSERIALIZABLE
transactions, with应该没问题READ ONLY
,只要你不明确地使用LOCK TABLE
。您还需要确保不使用可能在两组事务之间交互的咨询锁。很可能您根本不使用建议锁,并且可以完全忘记这一点。
但是,单独地,应用程序必须准备好处理序列化失败或其他事务中止。任何试图避免这种情况的设计都会被破坏。由于操作系统/主机级别问题、管理员操作等,事务可能会中止。不要依赖“不会失败”的事务。如果你绝对必须这样做,你需要使用两阶段提交,你
PREPARE TRANSACTION
(在这一点上保证 tx 不会提交失败),做其他依赖于 tx 安全提交的工作,然后COMMIT PREPARED
。如果其他工作出了问题,你可以ROLLBACK PREPARED
。2PC 有很大的开销,最好尽可能避免,但有时别无选择。