

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

# Amazon QLDB 中的日记账内容
<a name="journal-contents"></a>

**重要**  
终止支持通知：现有客户将能够使用 Amazon QLDB，直到 2025 年 7 月 31 日终止支持。有关更多详细信息，请参阅[将亚马逊 QLDB 账本迁移到亚马逊 Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)。

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

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

**Topics**
+ [

## 数据块示例
](#journal.block-example)
+ [

## 数据块内容
](#journal.block-contents)
+ [

## 已编校的修订版
](#journal.redacted-revisions)
+ [

## 示例应用程序
](#journal.sample)
+ [

## 另请参阅
](#journal.see-also)

## 数据块示例
<a name="journal.block-example"></a>

日记账数据块包含事务元数据、以及代表事务中提交的文档修订版本条目、和提交这些修订的 [PartiQL](ql-reference.md) 语句。

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

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

```
{
  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` 值而不包含其他属性。这是仅供内部使用的系统修订版，不包含用户数据。修订版的哈希值是该日记账完整哈希链的一部分，这是加密验证的必要条件。

## 数据块内容
<a name="journal.block-contents"></a>

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

**`blockAddress`**  
日记账中的数据库位置。地址是一种包含两个字段的 [Amazon Ion](ion.md) 结构：即`strandId`和`sequenceNo`。  
例如：`{strandId:"BlFTjlSXze9BIh1KOszcE3",sequenceNo:14}`

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

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

**`blockHash`**  
唯一代表数据块的 256 位哈希值。这是`entriesHash`和 `previousBlockHash`的串联的哈希值。

**`entriesHash`**  
代表数据块内所有条目的哈希值，包括仅限内部的系统条目。这是 [Merkle tree](verification.md#verification.how-it-works.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`— 由声明更新的文档 IDs 。每个文档都包括它所属的`tableName` 和 `tableId`，以及更新该文档的每条语句的索引。

**`revisions`**  
数据块中提交的文档修订列表。每个修订版本结构都包含所有此版本的所有[提交视图](working.metadata.md)字段。  
这也可以包括代表仅限内部的系统修订版哈希，这些版本是日记账账完整哈希链的一部分。

## 已编校的修订版
<a name="journal.redacted-revisions"></a>

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

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

### 已编校的修订示例
<a name="journal.redacted-revisions.example"></a>

考虑前面的 [数据块示例](#journal.block-example)。在此数据块，假设您编辑了文档 ID 为`HwVFkn8IMRa0xjze5xcgga`、版本号为`0`的修订版。

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

以下修订示例显示了此次密文的结果，其中突出显示了新`dataHash`字段。*red italics*

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

```
...
{
  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
    }
  ]
}
...
```

## 示例应用程序
<a name="journal.sample"></a>

有关使用导出数据验证期刊哈希链的 Java 代码示例，请参阅 GitHub 存储库 a [ws-samples/-amazon-qldb-dmv-sample](https://github.com/aws-samples/amazon-qldb-dmv-sample-java) java。此示例应用程序包含以下类别文件：
+ [ValidateQldbHashChain.java](https://github.com/aws-samples/amazon-qldb-dmv-sample-java/blob/master/src/main/java/software/amazon/qldb/tutorial/ValidateQldbHashChain.java)-包含从账本导出日记账区块并使用导出的数据验证区块之间的哈希链的教程代码。
+ [JournalBlock.java](https://github.com/aws-samples/amazon-qldb-dmv-sample-java/blob/master/src/main/java/software/amazon/qldb/tutorial/qldb/JournalBlock.java)-包含一个名为的方法`verifyBlockHash()`，该方法演示如何计算区块中的每个哈希分量。此方法由`ValidateQldbHashChain.java`中的教程代码调用。

有关如何下载和安装此完整示例应用程序的说明，请参阅 [安装 Amazon QLDB Java 示例应用程序](sample-app.java.md)。在运行教程代码之前，请确保按照[Java 教程](getting-started.java.tutorial.md)中的步骤 1—3 设置示例分类账并向其中加载示例数据。

## 另请参阅
<a name="journal.see-also"></a>

有关 QLDB 中的日记账的更多信息，请参阅以下主题：
+ [从Amazon QLDB 导出日记账数据](export-journal.md) — 了解如何将日记账数据导出至 Amazon Simple Storage Service（Amazon S3）。
+ [Amazon QLDB 流式传输日记账数据](streams.md)— 了解如何将日记账数据流式传输至 Amazon Kinesis Data Streams。
+ [Amazon QLDB 中的数据验证](verification.md) — 了解日记账数据的加密验证。