使用说明

本文将引导您完成从创建集群到首次成功访问的全过程,帮助您快速上手使用PolarDB PostgreSQLDynamoDB兼容功能。

前提条件

在使用DynamoDB兼容能力前,请确保您的集群版本满足以下要求:

  • 内核版本PostgreSQL 14,且修订版本需为2.0.14.17.35.0及以上。

  • 数据库代理版本:需为2.3.59及以上。

  • PolarDB PostgreSQL分布式版Serverless集群暂不支持DynamoDB兼容能力。

说明

您可前往PolarDB控制台,在集群的配置与管理 > 版本管理页面中查看对应的版本。若版本不满足要求,请升级对应的小版本

开启兼容DynamoDB能力

您可以通过以下两种方式为集群开启DynamoDB兼容功能。

已有集群

若您的集群满足前提条件,则可以在集群的基本信息页面中,找到DynamoDB兼容能力配置项,单击开启image

创建新集群

若您的集群不满足前提条件或希望在新的集群中使用当前功能,则可以在PolarDB控制台上创建一个新的集群。

  1. 前往PolarDB集群自定义购买页面

  2. 将数据库引擎设置为PostgreSQL 14,并勾选DynamoDB兼容能力

  3. 根据业务需求配置地域、可用区和节点规格等其他选项。

image

配置DynamoDB访问地址

开启DynamoDB兼容功能后,系统会自动创建一个默认的DynamoDB访问地址。您也可以创建自定义地址以满足特定需求。

  • 在集群基本信息页面的数据库连接区域,可以找到系统默认创建的DynamoDB地址

    image

  • (可选)单击创建自定义地址并选择地址类型为DynamoDB地址,可以为该地址指定挂载的节点并预设数据一致性级别。

    说明

    一致性级别在自定义地址上设定后,该地址下的所有读请求都将遵循此设置。当前不支持在单次API请求中通过ConsistentRead=true参数来覆盖地址上预设的一致性级别。

    image

创建DynamoDB专用账号

您需要创建一个专用的DynamoDB账号来获取用于API访问的身份凭证(AccessKey)。

  1. 在集群的配置与管理 > 账号管理页面,单击创建账号

  2. 将账号类型选择为DynamoDB账号,并设置账号名和密码。

    说明

    此处设置的密码仅用于在控制台管理该账号,并非API访问所用的密钥。

    image

  3. 创建成功后,在账号列表中找到该账号。账号名即为Access Key ID,单击密钥列的查看即可获取SecretAccess Keyimage

配置网络访问

根据您的服务器或客户端位置,选择合适的网络连接方式。

  • 私网连接(推荐) 如果您的应用程序部署在阿里云ECS上,请确保ECSPolarDB集群位于同一VPC内,并已将ECSIP地址或安全组添加到集群的白名单中。

  • 公网连接 如需在本地环境进行开发与测试,或当ECSPolarDB集群不位于同一VPC内时,您可以在集群基本信息页面的数据库连接区域,为DynamoDB地址申请一个公网地址。

    说明

    公网地址访问会增加安全风险。建议仅用于临时开发测试,完成后请及时释放公网地址。

    image

连接并验证

使用以下Python示例代码,通过Boto3 SDK验证您的配置是否正确。以下内容以ECS实例,Alibaba Cloud Linux 3.2104 LTS 64操作系统为例进行说明。

  1. 根据实际业务需求,进入指定的项目目录。此处以/home/testDynamoDB为例。

    mkdir /home/testDynamoDB
    cd /home/testDynamoDB
  2. /home/testDynamoDB目录中,创建虚拟环境(venv)隔离项目依赖,避免全局污染。

    python3 -m venv myenv
  3. 激活虚拟环境

    source myenv/bin/activate
  4. 安装所需的Python依赖库。

    pip3 install boto3
  5. 创建一个Python文件,并复制以下代码。请将endpoint_urlaws_access_key_id以及aws_secret_access_key替换为PolarDB集群的连接地址DynamoDB账号

    vim main.py
    import boto3
    from botocore.exceptions import ClientError
    
    # 1. Configure your connection details
    # Endpoint URL from Step 2
    endpoint_url = "http://<your-polardb-ddb-endpoint>:<port>"
    # Access Key ID from Step 3
    aws_access_key_id = "<your-access-key-id>"
    # Secret Access Key from Step 3
    aws_secret_access_key = "<your-secret-access-key>"
    # For PolarDB-DDB, region_name should be an empty string
    region_name = ""
    
    # 2. Create a DynamoDB resource client
    dynamodb = boto3.resource(
        'dynamodb',
        endpoint_url=endpoint_url,
        aws_access_key_id=aws_access_key_id,
        aws_secret_access_key=aws_secret_access_key,
        region_name=region_name,
    )
    
    table_name = 'usertable'
    
    # 3. Define functions for database operations
    def create_table():
        """Creates the table, or gets it if it already exists."""
        try:
            table = dynamodb.create_table(
                TableName=table_name,
                KeySchema=[{'AttributeName': 'userid', 'KeyType': 'HASH'}], # Partition key
                AttributeDefinitions=[{'AttributeName': 'userid', 'AttributeType': 'S'}]
                # ProvisionedThroughput is optional and ignored by PolarDB
            )
            print("Creating table... Waiting for it to become active.")
            table.meta.client.get_waiter('table_exists').wait(TableName=table_name)
            print("Table is active!")
            return table
        except ClientError as e:
            if e.response['Error']['Code'] == 'ResourceInUseException':
                print("Table already exists.")
                return dynamodb.Table(table_name)
            else:
                raise
    
    def put_items(table):
        """Puts a few items into the table."""
        users = [
            {'userid': 'user01', 'name': 'Alice', 'age': 24},
            {'userid': 'user02', 'name': 'Bob', 'age': 30},
            {'userid': 'user03', 'name': 'Charlie', 'age': 28}
        ]
        for user in users:
            table.put_item(Item=user)
        print("Inserted 3 items.")
    
    def scan_table(table):
        """Scans and prints all items in the table."""
        response = table.scan()
        items = response.get('Items', [])
        print(f"Scanned {len(items)} items:")
        for item in items:
            print(item)
    
    def delete_table(table):
        """Deletes the table."""
        table.delete()
        print("Deleting table... Waiting for it to be removed.")
        table.meta.client.get_waiter('table_not_exists').wait(TableName=table_name)
        print("Table deleted successfully.")
    
    # 4. Run the verification process
    if __name__ == '__main__':
        try:
            user_table = create_table()
            put_items(user_table)
            scan_table(user_table)
        finally:
            # Ensure the table is cleaned up even if errors occur
            if 'user_table' in locals():
                delete_table(user_table)
  6. 执行该脚本后,您应该会看到类似以下的输出:

    python3 main.py
    Creating table... Waiting for it to become active.
    Table is active!
    Inserted 3 items.
    Scanned 3 items:
    {'age': Decimal('24'), 'name': 'Alice', 'userid': 'user01'}
    {'age': Decimal('30'), 'name': 'Bob', 'userid': 'user02'}
    {'age': Decimal('28'), 'name': 'Charlie', 'userid': 'user03'}
    Deleting table... Waiting for it to be removed.
    Table deleted successfully.

    看到以上输出,表明您已成功连接并操作数据库,所有配置均已生效。