Amazon QLDB 中的日记账内容 - Amazon Quantum Ledger Database (Amazon QLDB)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon QLDB 中的日记账内容

在 Amazon QLDB 中,日记账是不可变的事务记录,用于存储数据的所有完整且可验证的更改历史记录。该日记账仅限追加,由一组有序和哈希链的数据块组成,其中包含您提交的数据和其他系统元数据。QLDB 在事务中向日记账中写入一个链式数据块。

本节介绍了包含样本数据的日记账数据块的示例,并描述了数据块的内容。

数据块示例

日记账数据块包含事务元数据、以及代表事务中提交的文档修订版本条目、和提交这些修订的 PartiQL 语句。

以下是包含示例数据的数据块示例。

注意

数据块示例仅用于参考。显示的哈希值并非实际计算的哈希值。

{
  blockAddress:{
    strandId:"4o5UuzWSW5PIoOGm5jPA6J",
    sequenceNo:25
  },
  transactionId:"3gtB8Q8dfIMA8lQ5pzHAMo",
  blockTimestamp:2022-06-08T18:46:46.512Z,
  blockHash:{{QS5lJt8vRxT30L9OGL5oU1pxFTe+UlEwakYBCrvGQ4A=}},
  entriesHash:{{buYYc5kV4rrRtJAsrIQnfnhgkzfQ8BKjI0C2vFnYQEw=}},
  previousBlockHash:{{I1UKRIWUgkM1X6042kcoZ/eN1rn0uxhDTc08zw9kZ5I=}},
  entriesHashList:[
    {{BUCXP6oYgmug2AfPZcAZup2lKolJNTbTuV5RA1VaFpo=}},
    {{cTIRkjuULzp/4KaUEsb/S7+TG8FvpFiZHT4tEJGcANc=}},
    {{3aktJSMyJ3C5StZv4WIJLu/w3D8mGtduZvP0ldKUaUM=}},
    {{GPKIJ1+o8mMZmPj/35ZQXoca2z64MVYMCwqs/g080IM=}}
  ],
  transactionInfo:{
    statements:[
      {
        statement:"INSERT INTO VehicleRegistration VALUE ?",
        startTime:2022-06-08T18:46:46.063Z,
        statementDigest:{{KY2nL6UGUPs5lXCLVXcUaBxcEIop0Jvk4MEjcFVBfwI=}}
      },
      {
        statement:"SELECT p_id FROM Person p BY p_id WHERE p.FirstName = ? and p.LastName = ?",
        startTime:2022-06-08T18:46:46.173Z,
        statementDigest:{{QS2nfB8XBf2ozlDx0nvtsliOYDSmNHMYC3IRH4Uh690=}}
      },
      {
        statement:"UPDATE VehicleRegistration r SET r.Owners.PrimaryOwner.PersonId = ? WHERE r.VIN = ?",
        startTime:2022-06-08T18:46:46.278Z,
        statementDigest:{{nGtIA9Qh0/dwIplOR8J5CTeqyUVtNUQgXfltDUo2Aq4=}}
      },
      {
        statement:"DELETE FROM DriversLicense l WHERE l.LicenseNumber = ?",
        startTime:2022-06-08T18:46:46.385Z,
        statementDigest:{{ka783dcEP58Q9AVQ1m9NOJd3JAmEvXLjzl0OjN1BojQ=}}
      }
    ],
    documents:{
      HwVFkn8IMRa0xjze5xcgga:{
        tableName:"VehicleRegistration",
        tableId:"HQZ6cgIMUi204Lq1tT4oaJ",
        statements:[0,2]
      },
      IiPTRxLGJZa342zHFCFT15:{
        tableName:"DriversLicense",
        tableId:"BvtXEB1JxZg0lJlBAtbtSV",
        statements:[3]
      }
    }
  },
  revisions:[
    {
      hash:{{FR1IWcWew0yw1TnRklo2YMF/qtwb7ohsu5FD8A4DSVg=}}
    },
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      hash:{{6TTHbcfIVdWoFC/j90BOZi0JdHzhjSXo1tW+uHd6Dj4=}},
      data:{
        VIN:"1N4AL11D75C109151",
        LicensePlateNumber:"LEWISR261LL",
        State:"WA",
        City:"Seattle",
        PendingPenaltyTicketAmount:90.25,
        ValidFromDate:2017-08-21,
        ValidToDate:2020-05-11,
        Owners:{
          PrimaryOwner:{
            PersonId:"3Ax20JIix5J2ulu2rCMvo2"
          },
          SecondaryOwners:[]
        }
      },
      metadata:{
        id:"HwVFkn8IMRa0xjze5xcgga",
        version:0,
        txTime:2022-06-08T18:46:46.492Z,
        txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
      }
    },
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      hash:{{ZVF/f1uSqd5DIMqzI04CCHaCGFK/J0Jf5AFzSEk0l90=}},
      metadata:{
        id:"IiPTRxLGJZa342zHFCFT15",
        version:1,
        txTime:2022-06-08T18:46:46.492Z,
        txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
      }
    }
  ]
}

revisions字段中,某些修订版本对象可能只包含一个 hash 值而不包含其他属性。这是仅供内部使用的系统修订版,不包含用户数据。修订版的哈希值是该日记账完整哈希链的一部分,这是加密验证的必要条件。

数据块内容

日记账数据块包含以下字段:

blockAddress

日记账中的数据库位置。地址是一种包含两个字段的 Amazon Ion 结构:即strandIdsequenceNo

例如:{strandId:"BlFTjlSXze9BIh1KOszcE3",sequenceNo:14}

transactionId

提交数据块的事务唯一 ID。

blockTimestamp

数据块提交到日记账的时间戳。

blockHash

唯一代表数据块的 256 位哈希值。这是entriesHashpreviousBlockHash的串联的哈希值。

entriesHash

代表数据块内所有条目的哈希值,包括仅限内部的系统条目。这是 Merkle tree的根哈希,其中叶节点由entriesHashList中的所有哈希组成。

previousBlockHash

日记账中前一个链式数据块的哈希值。

entriesHashList

代表数据块中每个条目的哈希列表。此列表可以包含以下条目哈希:

  • 表示transactionInfo的 Ion 哈希。该值是通过取整个 transactionInfo 结构的 Ion 哈希值计算得出的。

  • Merkle tree 的根哈希,其中叶节点由revisions中的所有哈希组成。

  • 表示redactionInfo的 Ion 哈希。此哈希值仅存在于由编校事务提交的数据块中。它的值是通过取整个 redactionInfo 结构的 Ion 哈希值计算得出的。

  • 代表仅限内部使用的系统元数据哈希。这些哈希值可能并不存在于所有数据块。

transactionInfo

一种 Amazon Ion 结构,其中包含有关提交数据块的事务中的语句的信息。此结构具有以下字段:

  • statements — PartiQL 语句列表以及它们何时开始运行的startTime。每个语句都有一个 statementDigest 哈希,这是计算 transactionInfo 结构哈希值所必需的。

  • documents — 由语句更新的文档 ID。每个文档都包括它所属的tableNametableId,以及更新该文档的每条语句的索引。

revisions

数据块中提交的文档修订列表。每个修订版本结构都包含所有此版本的所有提交视图字段。

这也可以包括代表仅限内部的系统修订版哈希,这些版本是日记账账完整哈希链的一部分。

已编校的修订版

在 Amazon QLDB,DELETE 语句只能通过创建将文档标记为已删除的新修订版,从逻辑上删除文档。QLDB 还支持数据编校操作,允许您永久删除表历史记录中的非活动文档修订版本。

编校操作仅删除指定修订版中的用户数据,而日记账序列和文档元数据则保持不变。这样可保持分类账的整体数据完整性。有关编校操作示例的更多信息,请参阅 对文档修订版执行编校

已编校的修订示例

考虑前面的 数据块示例。在此数据块,假设您编辑了文档 ID 为HwVFkn8IMRa0xjze5xcgga、版本号为0的修订版。

编校完成后,修订版中的用户数据 (由data结构表示) 将替换为一个新 dataHash 字段。该字段的值是已移除 data 结构的 Ion 哈希。因此,分类账保持了其整体数据的完整性,并通过现有验证 API 操作保持加密可验证性。

以下修订示例显示了此密文结果,新dataHash字段以红色斜体突出显示。

注意

本文档仅用于参考。显示的哈希值并非实际计算的哈希值。

...
{
  blockAddress:{
    strandId:"4o5UuzWSW5PIoOGm5jPA6J",
    sequenceNo:25
  },
  hash:{{6TTHbcfIVdWoFC/j90BOZi0JdHzhjSXo1tW+uHd6Dj4=}},
  dataHash:{{s83jd7sfhsdfhksj7hskjdfjfpIPP/DP2hvionas2d4=}},
  metadata:{
    id:"HwVFkn8IMRa0xjze5xcgga",
    version:0,
    txTime:2022-06-08T18:46:46.492Z,
    txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
  }
}
...

QLDB 还会在日记账中为已完成编辑请求添加新数据块。此数据块还包含其他 redactionInfo 条目,其中包含在事务中已编辑的修订的列表,如以下示例所示。

...
redactionInfo:{
  revisions:[
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      tableId:"HQZ6cgIMUi204Lq1tT4oaJ",
      documentId:"HwVFkn8IMRa0xjze5xcgga",
      version:0
    }
  ]
}
...

示例应用程序

有关使用导出数据验证日记账哈希链的 Java 代码示例,请参阅 GitHub 存储库 aws-samples/amazon-qldb-dmv-sample-java。此示例应用程序包含以下类别文件:

  • ValidateQldbHashChain.java - 包含从分类账中导出日记账账数据块、并使用导出的数据验证数据块之间哈希链的教程代码。

  • JournalBlock.java - 包含名为verifyBlockHash()的方法,该方法演示如何计算数据块中的每个哈希分量。此方法由ValidateQldbHashChain.java中的教程代码调用。

有关如何下载和安装此完整示例应用程序的说明,请参阅 安装 Amazon QLDB Java 示例应用程序。在运行教程代码之前,请确保按照Java 教程中的步骤 1—3 设置示例分类账并向其中加载示例数据。

另请参阅

有关 QLDB 中的日记账的更多信息,请参阅以下主题: