如何解决错误“ERROR: 1023 DETAIL: Serializable isolation violation on table in Redshift”?

上次更新日期:2022 年 10 月 10 日

如果我在不同会话中运行并发 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);
Session2_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 语句影响的表单。
  • 无论按什么顺序执行操作,都按相同的顺序锁定表单。
  • 在事务开始时锁定所有表单,然后才能执行任何操作。

对并发事务使用快照隔离

“序列化”选项执行严格的序列化,其中,如果结果无法映射到并发运行事务的序列顺序,则事务可能会失败。

“快照隔离”选项允许更高并发性,这样就可以成功完成对相同表格中的不同行的并发修改。

事务将会继续在数据库的最新提交版本或快照上运行。

使用 CREATE DATABASEALTER DATABASE 命令中的 ISOLATION LEVEL 参数在数据库上设置快照隔离。

要查看您的数据库正在使用的并发模型,请运行以下示例 STV_DB_ISOLATION_LEVEL 查询:

SELECT * FROM stv_db_isolation_level;
The database can then be altered to SNAPSHOT ISOLATION:
ALTER DATABASE sampledb ISOLATION LEVEL SNAPSHOT;

在更改数据库的隔离级别时,请考虑以下几点:

  • 您必须拥有当前数据库的超级用户或 CREATE DATABASE 权限,才能更改数据库隔离级别。
  • 您无法更改 DEV 数据库环境的隔离级别。
  • 您不能更改事务块中的隔离级别。
  • 如果其他用户连接到数据库,则更改隔离级别命令将失败。
  • 更改隔离级别命令可以更改当前会话的隔离级别设置。

这篇文章对您有帮助吗?


您是否需要账单或技术支持?