

# 在 DynamoDB 中请求表导出
<a name="S3DataExport_Requesting"></a>

DynamoDB 表导出支持您将表数据导出到 Amazon S3 存储桶，同时使您可以通过其它 AWS 服务（如 Athena、AWS Glue、Amazon SageMaker AI、Amazon EMR 和 AWS Lake Formation）对数据执行分析和复杂的查询。可以使用 AWS 管理控制台、AWS CLI 或 DynamoDB API 请求表导出。

**注意**  
不支持申请方付款 Amazon S3 存储桶。

DynamoDB 同时支持完整导出和增量导出：
+ 使用**完整导出**，可以在从时间点故障恢复（PITR）时段内的任何时间点，将表的完整快照导出到 Amazon S3 桶。
+ 通过**增量导出**，您可以将 DynamoDB 表中在 PITR 时段的指定时间段内已更改、更新或删除的数据导出到 AmazonS3 桶中。

**Topics**
+ [先决条件](#S3DataExport_Requesting_Permissions)
+ [请求使用 AWS 管理控制台 导出](#S3DataExport_Requesting_Console)
+ [获取 AWS 管理控制台 中以前导出的详细信息](#S3DataExport_Requesting_Console_Details)
+ [使用 AWS CLI 和 AWS SDK 请求导出](#S3DataExport_Requesting_CLI)
+ [使用 AWS CLI 和 AWS SDK 获取有关以前导出的详细信息](#S3DataExport_Requesting_CLI_Details)

## 先决条件
<a name="S3DataExport_Requesting_Permissions"></a>

**启用 PITR**

要使用导出到 S3 特征，您必须对表启用 PITR。有关如何启用 PITR 的详细信息，请参阅[时间点故障恢复](PointInTimeRecovery_Howitworks.md)。如果您请求导出未启用 PITR 的表，则请求将失败，并显示一条异常消息：“调用 `ExportTableToPointInTime` 操作时出现错误（PointInTimeRecoveryUnavailableException）：未为表“my-dynamodb-table”启用时间点恢复”。您只能从您配置的 PITR `RecoveryPeriodInDays` 内的时间点请求和导出。

**设置 S3 权限**

可以将表数据导出到具有写入权限的任何 Amazon S3 存储桶。目标存储桶无需与源表位于同一 AWS 区域中，也无需与源表具有同一拥有者。您的 AWS Identity and Access Management（IAM）策略需要允许您执行 S3 操作（`s3:AbortMultipartUpload`、`s3:PutObject` 和 `s3:PutObjectAcl`）和 DynamoDB 导出操作（`dynamodb:ExportTableToPointInTime`）。以下是一个示例策略，该策略将授予您的用户执行导出到 S3 存储桶的权限。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowDynamoDBExportAction",
            "Effect": "Allow",
            "Action": "dynamodb:ExportTableToPointInTime",
            "Resource": "arn:aws:dynamodb:us-east-1:111122223333:table/my-table"
        },
        {
            "Sid": "AllowS3BucketWrites",
            "Effect": "Allow",
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*"
        }
    ]
}
```

------

如果您需要写入其他账户中的 Amazon S3 存储桶，或者您没有写入权限，则 Amazon S3 存储桶拥有者必须添加存储桶策略来允许您从 DynamoDB 导出到该存储桶。以下是有关目标 Amazon S3 存储桶的策略示例。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "ExampleStatement",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:user/Dave"
            },
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*"
        }
    ]
}
```

------

导出时撤消这些权限将导致部分文件。

**注意**  
如果您要导出到的目标表或桶使用了客户管理的密钥加密，则该 KMS 密钥的策略必须赋予 DynamoDB 使用该密钥的权限。此权限是通过触发导出任务的 IAM 用户/角色授予的。有关加密的更多信息，包括最佳实践，请参阅 [DynamoDB 如何使用 AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/services-dynamodb.html) 和[使用自定义 KMS 密钥](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/encryption.howitworks.html#managed-key-customer-managed)。

## 请求使用 AWS 管理控制台 导出
<a name="S3DataExport_Requesting_Console"></a>

下面的示例演示如何使用 DynamoDB 控制台导出名为 `MusicCollection` 的现有表。

**注意**  
此过程假定已启用时间点恢复。要在 `MusicCollection` 表中启用，在表的**概述**选项卡的**表详细信息**部分，为**时间点恢复**选择**启用**。

**请求表导出**

1. 登录 AWS 管理控制台，打开 DynamoDB 控制台：[https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)。

1. 在控制台左侧的导航窗格中，选择**流和导出**。

1. 选择**导出到 S3** 按钮。

1. 选择源表和目标 S3 存储桶。如果目标存储桶为您的账户所拥有，则您可以使用 **Browse S3**（浏览 S3）按钮查找它。否则，使用 `s3://bucketname/prefix format.` 输入存储桶的 URL，**prefix** 是一个可选文件夹，有助于您的目标存储桶保持井然有序。

1. 选择**完整导出**或**增量导出**。**完整导出**会按照您指定的时间点输出表的完整表快照。**增量导出**会输出在指定的导出期间对表所做的更改。您的输出经过压缩，以便只包含导出期间项目的最终状态。即使该项目在同一导出期间内有多个更新，也只会在导出中出现一次。

------
#### [ Full export ]

   1. 选择要从中导出完整表快照的时间点。这可以是 PITR 时段内的任何时间点。或者，您可以选择**当前时间**以导出最新的快照。

   1. 对于**导出的文件格式**，请在 **DynamoDB JSON** 和 **Amazon Ion** 之间进行选择。默认表将从时间点恢复窗口中的最新可还原时间以 DynamoDB JSON 格式导出，并使用 Amazon S3 密钥 (SSE-S3) 加密。您可以根据需要更改这些导出设置。
**注意**  
如果选择使用 AWS Key Management Service (AWS KMS) 保护的密钥对导出进行加密，则密钥必须与目标 S3 存储桶位于同一区域。

------
#### [ Incremental export ]

   1. 选择要针对其导出增量数据的**导出期间**。在 PITR 时段中选择开始时间。导出期间持续时间必须至少为 15 分钟，且不超过 24 小时。导出期间的开始时间包含在内，结束时间不包括在内。

   1. 在**绝对模式**或**相对模式**之间进行选择。

      1. **绝对模式**将导出您指定的时间段内的增量数据。

      1. **相对模式**将在相对于导出任务提交时间的导出期间内导出增量数据。

   1. 对于**导出的文件格式**，请在 **DynamoDB JSON** 和 **Amazon Ion** 之间进行选择。默认表将从时间点恢复窗口中的最新可还原时间以 DynamoDB JSON 格式导出，并使用 Amazon S3 密钥 (SSE-S3) 加密。您可以根据需要更改这些导出设置。
**注意**  
如果选择使用 AWS Key Management Service (AWS KMS) 保护的密钥对导出进行加密，则密钥必须与目标 S3 存储桶位于同一区域。

   1. 对于**导出视图类型**，选择**新旧映像**或**仅限新映像**。新映像提供项目的最新状态。旧映像提供项目在指定的“开始日期和时间”之前的状态。原定设置为**新旧映像**。有关新映像和旧映像的更多信息，请参阅[增量导出输出](S3DataExport.Output.md#incremental-export-output)。

------

1. 选择**导出**以开始。

导出的数据在事务上不一致。您的事务操作可能会在两个导出输出之间发生损坏。可能通过导出中反映的事务操作修改了项目的子集，而同一事务中的另一个修改子集未反映在同一个导出请求中。但是，导出最终是一致的。如果事务在导出过程中损坏，则您将在下一次相邻导出中具有剩余的事务，而没有重复。用于导出的时间段基于内部系统时钟，可能与应用程序的本地时钟相差一分钟。

## 获取 AWS 管理控制台 中以前导出的详细信息
<a name="S3DataExport_Requesting_Console_Details"></a>

通过选择导航侧边栏中的**导出到 S3** 部分，可以找到有关您过去运行的导出任务的信息。此部分包含过去 90 天内创建的所有导出的列表。选择**导出**选项卡中所列任务的 ARN 来检索有关该导出的信息，包括您选择的任何高级配置设置。请注意，尽管导出任务元数据会在 90 天后过期，列表中没有早于该日期的作业，但 S3 存储桶中的数据元将保持存储桶策略允许的时间。导出时，DynamoDB 不删除 S3 存储桶中创建的任何对象。

## 使用 AWS CLI 和 AWS SDK 请求导出
<a name="S3DataExport_Requesting_CLI"></a>

下面的示例演示如何将现有表导出到 S3 存储桶。

**注意**  
此过程假定您已启用时间点故障恢复。要为 `MusicCollection` 表启用，请运行下面的命令。  

```
aws dynamodb update-continuous-backups \
    --table-name MusicCollection \
    --point-in-time-recovery-specification PointInTimeRecoveryEnabled=True
```

**完整导出**

------
#### [ AWS CLI ]

**注意**  
如果请求跨账户表导出，请务必包含 `--s3-bucket-owner` 选项。

```
aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-west-2:111122223333:table/MusicCollection \
  --s3-bucket ddb-export-musiccollection-9012345678 \
  --s3-prefix 2020-Nov \
  --export-format DYNAMODB_JSON \
  --export-time 1604632434 \
  --s3-bucket-owner 9012345678 \
  --s3-sse-algorithm AES256
```

------
#### [ Python ]

```
import boto3
from datetime import datetime

client = boto3.client('dynamodb')

client.export_table_to_point_in_time(
    TableArn='arn:aws:dynamodb:us-east-1:111122223333:table/TABLE',
    ExportTime=datetime(2023, 9, 20, 12, 0, 0),
    S3Bucket='bucket',
    S3Prefix='prefix',
    S3SseAlgorithm='AES256',
    ExportFormat='DYNAMODB_JSON'
)
```

------
#### [ Java ]

```
DynamoDbClient client = DynamoDbClient.create();

client.exportTableToPointInTime(b -> b
    .tableArn("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE")
    .exportTime(Instant.parse("2023-09-20T12:00:00Z"))
    .s3Bucket("bucket")
    .s3Prefix("prefix")
    .s3SseAlgorithm(S3SseAlgorithm.AES256)
    .exportFormat(ExportFormat.DYNAMODB_JSON));
```

------
#### [ .NET ]

```
var client = new AmazonDynamoDBClient();

await client.ExportTableToPointInTimeAsync(new ExportTableToPointInTimeRequest
{
    TableArn = "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE",
    ExportTime = new DateTime(2023, 9, 20, 12, 0, 0, DateTimeKind.Utc),
    S3Bucket = "bucket",
    S3Prefix = "prefix",
    S3SseAlgorithm = S3SseAlgorithm.AES256,
    ExportFormat = ExportFormat.DYNAMODB_JSON
});
```

------
#### [ JavaScript ]

```
import { DynamoDBClient, ExportTableToPointInTimeCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient();

await client.send(new ExportTableToPointInTimeCommand({
    TableArn: "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE",
    ExportTime: new Date("2023-09-20T12:00:00Z"),
    S3Bucket: "bucket",
    S3Prefix: "prefix",
    S3SseAlgorithm: "AES256",
    ExportFormat: "DYNAMODB_JSON"
}));
```

------
#### [ Go ]

```
cfg, _ := config.LoadDefaultConfig(context.TODO())
client := dynamodb.NewFromConfig(cfg)

exportTime := time.Date(2023, 9, 20, 12, 0, 0, 0, time.UTC)
client.ExportTableToPointInTime(context.TODO(), &dynamodb.ExportTableToPointInTimeInput{
    TableArn:       aws.String("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"),
    ExportTime:     &exportTime,
    S3Bucket:       aws.String("bucket"),
    S3Prefix:       aws.String("prefix"),
    S3SseAlgorithm: types.S3SseAlgorithmAes256,
    ExportFormat:   types.ExportFormatDynamodbJson,
})
```

------

**增量导出**

------
#### [ AWS CLI ]

```
aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:REGION:ACCOUNT:table/TABLENAME \
  --s3-bucket BUCKET --s3-prefix PREFIX \
  --incremental-export-specification ExportFromTime=1693569600,ExportToTime=1693656000,ExportViewType=NEW_AND_OLD_IMAGES \
  --export-type INCREMENTAL_EXPORT
```

------
#### [ Python ]

```
import boto3
from datetime import datetime

client = boto3.client('dynamodb')

client.export_table_to_point_in_time(
    TableArn='arn:aws:dynamodb:us-east-1:111122223333:table/TABLE',
    IncrementalExportSpecification={
      'ExportFromTime': datetime(2023, 9, 20, 12, 0, 0),
      'ExportToTime': datetime(2023, 9, 20, 13, 0, 0),
      'ExportViewType': 'NEW_AND_OLD_IMAGES'
    },
    ExportType='INCREMENTAL_EXPORT',
    S3Bucket='bucket',
    S3Prefix='prefix',
    S3SseAlgorithm='AES256',
    ExportFormat='DYNAMODB_JSON'
)
```

------
#### [ Java ]

```
DynamoDbClient client = DynamoDbClient.create();

client.exportTableToPointInTime(b -> b
    .tableArn("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE")
    .exportType(ExportType.INCREMENTAL_EXPORT)
    .incrementalExportSpecification(i -> i
        .exportFromTime(Instant.parse("2023-09-20T12:00:00Z"))
        .exportToTime(Instant.parse("2023-09-20T13:00:00Z"))
        .exportViewType(ExportViewType.NEW_AND_OLD_IMAGES))
    .s3Bucket("bucket")
    .s3Prefix("prefix")
    .s3SseAlgorithm(S3SseAlgorithm.AES256)
    .exportFormat(ExportFormat.DYNAMODB_JSON));
```

------
#### [ .NET ]

```
var client = new AmazonDynamoDBClient();

await client.ExportTableToPointInTimeAsync(new ExportTableToPointInTimeRequest
{
    TableArn = "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE",
    ExportType = ExportType.INCREMENTAL_EXPORT,
    IncrementalExportSpecification = new IncrementalExportSpecification
    {
        ExportFromTime = new DateTime(2023, 9, 20, 12, 0, 0, DateTimeKind.Utc),
        ExportToTime = new DateTime(2023, 9, 20, 13, 0, 0, DateTimeKind.Utc),
        ExportViewType = ExportViewType.NEW_AND_OLD_IMAGES
    },
    S3Bucket = "bucket",
    S3Prefix = "prefix",
    S3SseAlgorithm = S3SseAlgorithm.AES256,
    ExportFormat = ExportFormat.DYNAMODB_JSON
});
```

------
#### [ JavaScript ]

```
import { DynamoDBClient, ExportTableToPointInTimeCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient();

await client.send(new ExportTableToPointInTimeCommand({
    TableArn: "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE",
    ExportType: "INCREMENTAL_EXPORT",
    IncrementalExportSpecification: {
        ExportFromTime: new Date("2023-09-20T12:00:00Z"),
        ExportToTime: new Date("2023-09-20T13:00:00Z"),
        ExportViewType: "NEW_AND_OLD_IMAGES"
    },
    S3Bucket: "bucket",
    S3Prefix: "prefix",
    S3SseAlgorithm: "AES256",
    ExportFormat: "DYNAMODB_JSON"
}));
```

------
#### [ Go ]

```
cfg, _ := config.LoadDefaultConfig(context.TODO())
client := dynamodb.NewFromConfig(cfg)

fromTime := time.Date(2023, 9, 20, 12, 0, 0, 0, time.UTC)
toTime := time.Date(2023, 9, 20, 13, 0, 0, 0, time.UTC)
client.ExportTableToPointInTime(context.TODO(), &dynamodb.ExportTableToPointInTimeInput{
    TableArn:   aws.String("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"),
    ExportType: types.ExportTypeIncrementalExport,
    IncrementalExportSpecification: &types.IncrementalExportSpecification{
        ExportFromTime: &fromTime,
        ExportToTime:   &toTime,
        ExportViewType: types.ExportViewTypeNewAndOldImages,
    },
    S3Bucket:       aws.String("bucket"),
    S3Prefix:       aws.String("prefix"),
    S3SseAlgorithm: types.S3SseAlgorithmAes256,
    ExportFormat:   types.ExportFormatDynamodbJson,
})
```

------

**注意**  
如果选择使用 AWS Key Management Service (AWS KMS) 保护的密钥对导出进行加密，则密钥必须与目标 S3 存储桶位于同一区域。

## 使用 AWS CLI 和 AWS SDK 获取有关以前导出的详细信息
<a name="S3DataExport_Requesting_CLI_Details"></a>

可以使用 `list-exports` 命令，查找有关以前运行的导出请求的信息。此命令返回过去 90 天创建的所有导出的列表。请注意，尽管导出任务元数据会在 90 天后过期，`list-exports` 命令不再返回早于该日期的作业，但 S3 存储桶中的数据元将保持存储桶策略允许的时间。导出时，DynamoDB 不删除 S3 存储桶中创建的任何对象。

导出的状态为 `PENDING`，直到成功或失败。如果成功，状态将更改为 `COMPLETED`。如果失败，状态将更改为 `FAILED`，并带有 `failure_message` 和 `failure_reason`。

**列表导出**

------
#### [ AWS CLI ]

```
aws dynamodb list-exports \
    --table-arn arn:aws:dynamodb:us-east-1:111122223333:table/ProductCatalog
```

------
#### [ Python ]

```
import boto3

client = boto3.client('dynamodb')

print(
  client.list_exports(
     TableArn='arn:aws:dynamodb:us-east-1:111122223333:table/TABLE',
  )
)
```

------
#### [ Java ]

```
DynamoDbClient client = DynamoDbClient.create();

ListExportsResponse response = client.listExports(b -> b
    .tableArn("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"));

response.exportSummaries().forEach(System.out::println);
```

------
#### [ .NET ]

```
var client = new AmazonDynamoDBClient();

var response = await client.ListExportsAsync(new ListExportsRequest
{
    TableArn = "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"
});

response.ExportSummaries.ForEach(Console.WriteLine);
```

------
#### [ JavaScript ]

```
import { DynamoDBClient, ListExportsCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient();

const response = await client.send(new ListExportsCommand({
    TableArn: "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"
}));

console.log(response.ExportSummaries);
```

------
#### [ Go ]

```
cfg, _ := config.LoadDefaultConfig(context.TODO())
client := dynamodb.NewFromConfig(cfg)

response, _ := client.ListExports(context.TODO(), &dynamodb.ListExportsInput{
    TableArn: aws.String("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE"),
})

fmt.Println(response.ExportSummaries)
```

------

**描述导出**

------
#### [ AWS CLI ]

```
aws dynamodb describe-export \
    --export-arn arn:aws:dynamodb:us-east-1:111122223333:table/ProductCatalog/export/01695353076000-a1b2c3d4
```

------
#### [ Python ]

```
import boto3

client = boto3.client('dynamodb')

print(
  client.describe_export(
     ExportArn='arn:aws:dynamodb:us-east-1:111122223333:table/TABLE/export/01695353076000-06e2188f',
  )['ExportDescription']
)
```

------
#### [ Java ]

```
DynamoDbClient client = DynamoDbClient.create();

DescribeExportResponse response = client.describeExport(b -> b
    .exportArn("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE/export/01695353076000-06e2188f"));

System.out.println(response.exportDescription());
```

------
#### [ .NET ]

```
var client = new AmazonDynamoDBClient();

var response = await client.DescribeExportAsync(new DescribeExportRequest
{
    ExportArn = "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE/export/01695353076000-06e2188f"
});

Console.WriteLine(response.ExportDescription);
```

------
#### [ JavaScript ]

```
import { DynamoDBClient, DescribeExportCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient();

const response = await client.send(new DescribeExportCommand({
    ExportArn: "arn:aws:dynamodb:us-east-1:111122223333:table/TABLE/export/01695353076000-06e2188f"
}));

console.log(response.ExportDescription);
```

------
#### [ Go ]

```
cfg, _ := config.LoadDefaultConfig(context.TODO())
client := dynamodb.NewFromConfig(cfg)

response, _ := client.DescribeExport(context.TODO(), &dynamodb.DescribeExportInput{
    ExportArn: aws.String("arn:aws:dynamodb:us-east-1:111122223333:table/TABLE/export/01695353076000-06e2188f"),
})

fmt.Println(response.ExportDescription)
```

------