Consistent reads are not supported on global secondary indexes

TL;DR — 你在一個以全域secondary index 為目標的 QueryScan 上設定了 ConsistentRead: true。GSI 以非同步方式從基礎表格複製,且只提供最終一致讀取 — 這個旗標是硬性錯誤,而非偏好設定。移除該旗標;如果你真的需要寫後即讀的一致性,改讀基礎表格(或將該鍵設計進 LSI)。

這是什麼意思

ValidationException: Consistent reads are not supported on global secondary indexes

GSI 在實體上是它自己的索引結構,有自己的 partition 與容量;DynamoDB 以非同步方式將基礎表格的寫入傳播到其中。由於你剛寫入的項目可能尚未抵達索引,DynamoDB 無法對它兌現強一致讀取 — 因此 ConsistentRead: true 與 GSI IndexName 結合會被直接拒絕。AWS 文件明確指出:以 ConsistentRead 設為 true 查詢 GSI,你會收到 ValidationException

Local secondary index 則不同:LSI 與基礎表格共用其 partition,因此那裡支援 ConsistentRead: true

為什麼會發生

  • 旗標被全域設定 — 共用的查詢輔助程式或用戶端包裝器對每次讀取預設 ConsistentRead: true,而某條呼叫路徑加了指向 GSI 的 IndexName
  • LSI 變成了 GSI — 為 local 索引撰寫的程式碼(旗標在那裡合法)被指向了 global 索引。
  • 複製貼上的基礎表格查詢 — 一個在表格上合法使用強一致的查詢被重用並加上了 IndexName

如何修正

  1. 從 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'}}
      })
    );
  2. 需要寫後即讀?ConsistentRead: true 查詢基礎表格 — 只要你要查找的鍵是表格自己的 partition key,就可行。

  3. 相同 partition key、不同 sort? 將它建模為 LSI(在建立表格時建立),它支援一致讀取。

  4. 或在應用中吸收延遲 — GSI 傳播通常很快;對 UI 流程而言,回傳你手上已有的剛寫入資料,勝過重新讀取索引。

DynoTable 桌面應用程式顯示每個表格的索引並讓你直接查詢它們 — 而且因為它知道哪個索引是全域、哪個是本地,這類錯誤根本不會出現。

相關錯誤

References

最後驗證於 2026-07-13,對照上方連結的 AWS 官方文件。

不必透過主控台就能操作 DynamoDB

DynoTable 是一款快速的 DynamoDB 桌面用戶端 — 瀏覽表格、執行 SQL 風格的查詢,並在本機編輯項目。