当我在不同会话中运行并发 Amazon Redshift 操作时,收到了消息“ERROR: 1023 DETAIL: Serializable isolation violation on table in Redshift”。 如何解决此错误?
Amazon Redshift 中的并发写入操作必须可序列化。这意味着,必须至少有一个将产生相同结果的订单中能够连续地运行事务,如同事务是在并发运行那样。有关详细信息,请参阅可序列化隔离。
使用下面的一种或两种方法来解决可序列化隔离错误:
- 移动为获得事务外原子性不必出现在相同事务中的操作
- 使每个会话锁定所有表单以强制序列化
移动为获得事务外原子性不必出现在相同事务中的操作
这适用于两个事务中的各个操作相互交叉引用并可能影响另一个事务的结果的情况。例如,假定两个会话各自发起一个事务:
Session1_Redshift = # BEGIN;
Session2_Redshift = # BEGIN;
每个事务中的 SELECT 语句的结果可能受另一个事务中的 INSERT 语句影响。如果按任何顺序连续运行,一个 SELECT 语句的结果始终会比并发交易多返回一个行。由于任何顺序都不能使操作连续运行并产生与并发运行时相同的结果,因此执行的最后一个操作会产生可序列化隔离错误:
Session1_redshift=# select * from tab1; Session1_redshift =# insert into tab2 values (1);
Session2_redshift =# insert into tab1 values (1); Session1_redshift =# select * from tab2;
如果 SELECT 语句的结果不重要(即事务中的操作的原子性不重要),请将 SELECT 语句移出其交易,如以下示例所示:
Session1_Redshift=# BEGIN; Session1_Redshift = # insert into tab1 values (1) Session1_Redshift = # END; Session1_Redshift # select * from tab2;
Session2_Redshift # select * from tab1; Session2_Redshift =# BEGIN; Session2_Redshift = # insert into tab2 values (1) Session2_Redshift = # END;
在这些示例中,事务中没有交叉引用。两个 INSERT 语句不会相互影响。由于至少有一个订单中的事务可以连续运行并产生与并发运行时相似的结果,因此这些事务可序列化。
锁定每个会话中的所有表单以强制序列化
LOCK 命令会阻挡将产生可序列化隔错误的操作。当您使用 LOCK 命令时,请务必执行以下操作:
- 锁定所有事务受影响的表单,包括事务内的只读 SELECT 语句影响的表单。
- 无论按什么顺序执行操作,都按相同的顺序锁定表单。
- 在事务开始时锁定所有表单,然后才能执行任何操作。