Aurora DSQL 中的并发控制
并发可让多个会话同时访问和修改数据,而不会损害数据完整性和一致性。Aurora DSQL 在实施现代、无锁并发控制机制的同时提供 PostgreSQL 兼容性。它通过快照隔离来保持完全的 ACID 合规性,同时确保数据一致性和可靠性。
Aurora DSQL 的一个关键优势是其无锁架构,这消除了常见的数据库性能瓶颈。Aurora DSQL 可防止慢速事务阻塞其它操作,并消除死锁风险。这种方法使 Aurora DSQL 对于性能和可扩展性至关重要的高吞吐量应用程序特别有价值。
并发控制响应
Aurora DSQL 使用乐观并发控制(OCC),其工作原理与传统的基于锁的系统不同。OCC 不使用锁,而是在提交时评估冲突。此提交时冲突评估过程也称为判定。Aurora DSQL 在检测到冲突时,会返回带有 SQLSTATE 代码 40001 的 PostgreSQL 序列化失败故障。响应消息包括标识冲突类型的 OCC 代码:
- OC000:数据冲突
-
两个事务试图修改同一行。提交时间最早的事务成功,而冲突的事务则收到 OC000 响应:
ERROR: change conflicts with another transaction (OC000) (SQLSTATE 40001) - OC001:架构冲突
-
会话所缓存的架构目录已过期。Aurora DSQL 检测到自会话加载其缓存以来目录版本发生了更改,并且事务无法安全地重定基准到当前版本时,事务将收到 OC001 响应:
ERROR: schema has been updated by another transaction (OC001) (SQLSTATE 40001)任何修改架构目录的操作都可能导致 OC001 响应,包括
CREATE TABLE和ALTER TABLE等 DDL 语句,以及GRANT和REVOKE语句。有关更多信息,请参阅 Aurora DSQL 中的 DDL 和分布式事务。
设计应用程序以实施重试逻辑来处理这些响应。理想的设计模式是幂等的,尽可能将事务重试作为第一选择。建议采用的逻辑类似于标准 PostgreSQL 锁定超时或死锁情况下的中止和重试逻辑。然而,OCC 要求您的应用程序更频繁地实施此逻辑。
数据冲突类型
由于 Aurora DSQL 的并发控制机制,SELECT ... FOR
UPDATE 和 SELECT ... FOR KEY SHARE 子句通过提交时的乐观冲突检测(而非锁定)来产生结果。在 Aurora DSQL 中,当一个事务写入某个行,并且另一个事务使用上述某个子句读取该行时,可能会在提交时发生冲突,具体取决于事务所使用的列。以下子句可决定 Aurora DSQL 检测这些冲突的方式。
键列定义
键列是指属于唯一、非部分、非表达式索引的列。所有其他列都为非键列。
SELECT ... FOR UPDATE-
声明 Aurora DSQL 将按事务对选定行进行写入的方式来对这些行进行冲突判定。如果另一个事务在同一行上运行
UPDATE、DELETE、SELECT ... FOR UPDATE或SELECT ... FOR KEY SHARE,并且首先提交,则运行了SELECT ... FOR UPDATE的事务将失败,并返回OC000响应。此子句与对行进行的任何并发写入,以及并发的FOR UPDATE或FOR KEY SHARE读取发生冲突。 SELECT ... FOR KEY SHARE-
声明事务依赖于选定行的键列。如果另一个事务删除行,更改其键列或运行
SELECT ... FOR UPDATE且首先提交,则运行了SELECT ... FOR KEY SHARE的事务将失败,并返回OC000响应。对非键列进行的并发UPDATE操作不会产生冲突。
Aurora DSQL 不支持 NO KEY UPDATE 或 FOR SHARE 子句。不过,DML 隐式使用 NO KEY UPDATE 机制。以下矩阵汇总了访问同一行的两个并发事务发生冲突的情况。X 表示这两个操作发生冲突:无论哪个事务最后提交,都将失败并返回 OC000 响应。空白单元格表示两个事务都可提交。
| 操作 | INSERT、DELETE、UPDATE(键列)或 SELECT ... FOR UPDATE |
UPDATE(仅限非键列) |
SELECT ... FOR KEY SHARE |
|---|---|---|---|
INSERT、DELETE、UPDATE(键列)或 SELECT ... FOR UPDATE |
X | X | X |
UPDATE(仅限非键列) |
X | X | |
SELECT ... FOR KEY SHARE |
X |
优化事务性能的准则
要优化性能,请尽量减少对单个键或小键范围的高度争用。要实现此目标,请按照以下准则设计架构,使其在集群键范围内分散更新:
-
为表选择一个随机主键。
-
避免使用会增加单个键争用的模式。即使在事务量增长的情况下,这种方法也能确保最佳性能。