Consistent reads are not supported on global secondary indexes
TL;DR — 你在一个针对全局二级索引的 Query 或 Scan 上设置了 ConsistentRead: true。GSI 从基础表异步复制,只提供最终一致性读取——这个标志是一个硬性错误,而非偏好设置。去掉该标志,或者如果你确实需要写后读一致性,就读取基础表(或者把该键设计进一个 LSI)。
含义
ValidationException: Consistent reads are not supported on global secondary indexes一个 GSI 在物理上是它自己的索引结构,有自己的分区和容量;DynamoDB 会把基础表的写入异步地传播进去。因为你刚写入的项目可能还没到达索引,DynamoDB 无法对它兑现一个强一致性读取——因此 ConsistentRead: true 与 GSI 的 IndexName 组合会被直接拒绝。AWS 文档说得很明确:用 ConsistentRead 设为 true 查询一个 GSI,你会收到 ValidationException。
本地二级索引则不同:一个 LSI 与基础表共享其分区,因此那里支持 ConsistentRead: true。
为什么会发生
- 该标志被全局设置——一个共享的查询辅助工具或客户端封装为每次读取默认设置
ConsistentRead: true,而某条调用路径添加了一个指向 GSI 的IndexName。 - 一个 LSI 变成了 GSI——为本地索引(那里该标志合法)编写的代码被指向了一个全局索引。
- 复制粘贴的基础表查询——一个在表上合法地使用了强一致性的查询,被加上
IndexName后重用了。
如何修复
从 GSI 读取中移除
ConsistentRead(或把它设为false——默认值):await client.send( new QueryCommand({ TableName: 'Orders', IndexName: 'status-index', KeyConditionExpression: '#s = :open', // ConsistentRead: true ← delete this line for a GSI ExpressionAttributeNames: {'#s': 'status'}, ExpressionAttributeValues: {':open': {S: 'OPEN'}} }) );需要写后读? 用
ConsistentRead: true查询基础表——只要你要查找的键是表自己的分区键,就可以做到。相同的分区键,不同的排序? 把它建模为一个 LSI(在表创建时创建),它支持一致性读取。
或者在应用中吸收这个延迟——GSI 传播通常很快;对于 UI 流程,返回你已经拥有的刚写入的数据胜过重新读取索引。
DynoTable 桌面应用会显示每张表的索引并让你直接查询它们——而且因为它知道哪个索引是全局的、哪个是本地的,这类错误压根不会出现。
相关错误
- GSI throttles the base table——GSI 的写入侧耦合。
- The table does not have the specified index
- Cannot update GSI while it is being created
- 代码示例:Query a GSI in Node.js——一个做对了的最终一致性 GSI 查询。
- 学习:Why GSIs are eventually consistent · GSI vs LSI · Consistency
References
- Query — Amazon DynamoDB API Reference
- Using Global Secondary Indexes in DynamoDB — Amazon DynamoDB Developer Guide
- Constraints in Amazon DynamoDB — Amazon DynamoDB Developer Guide
最后核实于 2026-07-13,依据上方链接的 AWS 官方文档。