[Like]可重复读取级别,由于序列化失败,必须准备使用此级别的应用程序重试事务。
在可重复读取或可序列化级别遇到序列化失败的条件是什么?
我试图在运行psql
的两个实例的情况下导致序列化失败,但即使事务是由一个实例提交的,另一个实例在可序列化级别的事务中,而另一个实例也是成功的承诺改变。两者都只是将记录插入表中,所以我可能需要尝试更复杂的东西。
基本上我试图了解序列化失败时会发生什么以及序列化失败的原因。
答案 0 :(得分:6)
序列化失败有很多可能的原因。从技术上讲,两个事务之间的死锁是序列化失败的一种形式,如果对模式(数据库结构)进行并发修改,则可能发生在任何隔离级别。既然你在询问PostgreSQL,你应该知道在PostgreSQL中,这种类型的序列化失败会从其他类型获得单独的SQLSTATE:'40P01'。所有其他序列化失败返回'40001'。这个答案的其余部分将集中在PostgreSQL中的这些非死锁变种。
在活动副本(“热备用”)之外,这些只能在两个更严格的隔离级别发生:REPEATABLE READ和SERIALIZABLE。在REPEATABLE READ级别,这些只能由于写入冲突而发生 - 两个并发事务尝试更新或删除相同(现有)行。进行尝试的第一个事务锁定行并继续。如果提交,则第二个事务因序列化失败而失败。如果第一个事务因任何原因回滚,则被阻止的事务将被释放以继续,并将在该行上获取自己的锁。此行为与事务持续时间内的单个“快照”结合使用,也称为“快照隔离”。
在PostgreSQL版本9.1之前,SERIALIZABLE事务的工作方式完全相同。从9.1开始PostgreSQL使用一种名为Serializable Snapshot Isolation的新技术来确保任何可序列化事务集的行为与这些事务的某些串行(一次一个)执行完全一致。在9.1中使用SERIALIZABLE事务时,您的应用程序应该为除ROLLBACK之外的任何语句的序列化失败做好准备 - 即使在只读事务中甚至在COMMIT上也是如此。有关更多信息,请参阅http://www.postgresql.org/docs/current/interactive/transaction-iso.html或Wiki页面上的PostgreSQL文档页面,其中提供了在http://wiki.postgresql.org/wiki/SSI
的新的更严格的隔离级别中如何发生序列化失败的示例如果您正在使用Hot Standby功能,如果存在长时间运行的查询,则可能会在只读副本上发生序列化故障,维护稳定的数据视图需要数据库阻止复制长。有一些配置设置可以让您平衡复制数据的“新鲜度”与长时间运行查询的容差。某些用户可能希望创建多个副本,以便他们可以拥有最新数据(甚至可能选择同步复制),同时允许另一个副本根据需要延迟为长时间运行的查询提供服务。
编辑以提供另一个链接:在第38届超大型数据库国际会议上发表的题为Serializable Snapshot Isolation in PostgreSQL的论文提供了比其他链接更多的细节和观点,以及为此奠定基础的论文的参考文献实施
答案 1 :(得分:5)
对于REPEATABLE READ
,此示例将执行:
准备阶段:
psql-0> CREATE TABLE foo(key int primary key, val int);
CREATE TABLE
psql-0> INSERT INTO foo VALUES(1, 42);
现在请关注psql- X 部分,指示操作的交错:
psql-1> BEGIN ISOLATION LEVEL REPEATABLE READ;
psql-1> UPDATE foo SET val=val+1;
UPDATE 1
psql-2> BEGIN ISOLATION LEVEL REPEATABLE READ;
psql-2> UPDATE foo SET val=val+1;
*** no output, transaction blocked ***
psql-1> COMMIT;
psql-2> *** unblocks ***
ERROR: could not serialize access due to concurrent update
SERIALIZABLE
的示例在PostgreSQL 9.1的文档中,从这里开始应该没问题。
答案 2 :(得分:4)
如果这有助于任何人,这里是Freenode上#postgresql的成绩单:
[14:36]< dtrebbien> What are the conditions for encountering a serialization failure?
[14:36]< dtrebbien> ^遇到的条件是什么? 序列化失败?
[14:37]< dtrebbien>是否有可以识别的PostgreSQL开发人员 序列化失败的条件?
[14:38]< peerce> http://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-SERIALIZABLE
[14:43]< dtrebbien> “任何可并行序列化的集合 交易将具有与在a处运行交易相同的效果 时间“
[14:44]< dtrebbien> PostgreSQL有哪些规则 引擎跟着?
[14:44]< dtrebbien>即如果更改了一行,是否会触发 失败了?
[14:44]< johto> 9.1中的可序列化隔离模式确实如此 复杂的
[14:45]< dtrebbien>我想。
[14:45]< dtrebbien>我也读到了Serializable级别 以某种方式“修复”
[14:45]< RhodiumToad> dtrebbien:在9.1之前,基本规则是 如果事务尝试更改当前值不是的行 可见,这是一个失败
[14:46]< dtrebbien> RhodiumToad:这很有趣。
[14:46]< dtrebbien>另外,访问一个值,对吗?
[14:46]< selenamarie> dtrebbien:除了别的什么 说,其背后的基本前提是检测周期 依赖
[14:47]< dtrebbien>哦。
[14:50]< dtrebbien>可以公平地说,9.1中的规则 触发隔离级别已变得更加复杂 基本上减少了“假阳性”序列化异常?
[14:51]< johto>它们变得复杂,因为它更简单 rulex没有捕获所有序列化异常
[14:51]< dtrebbien>啊!我明白了。
[14:51]< dtrebbien>这就是发行说明所说的原因 “固定的”。
[14:52]< RhodiumToad> dtrebbien:访问不可见的值 这不是一个错误,因为它只是获得了可见的值 快照的时间。
[14:53]< RhodiumToad> dtrebbien:只读可序列化查询 只需查看数据库的快照时间的静态状态。
[14:54]< RhodiumToad> dtrebbien:除了小皱纹外 TRUNCATE,所有序列化问题都涉及读/写查询
[15:03]< dtrebbien> RhodiumToad,johto,selenamarie和peerce: 你介意我把这个对话的成绩单发给Stack吗? 溢出?
[15:07]< selenamarie> dtrebbien:当然:))
[15:07]< dtrebbien>我不知道它是否会对任何人有所帮助。它 威力。
[15:08]< selenamarie> dtrebbien:我发布了凯文的笔记 Grittner在这里谈到这个问题: http://www.chesnok.com/daily/2011/03/24/raw-notes-from-kevin-grittners-talk-on-ssi/