创建读取副本

本页介绍如何创建 Cloud SQL 实例的只读副本。

只读副本是主实例的副本,可几乎实时地反映主实例的更改。您可以使用只读副本从主实例中分流读取请求或分析流量。

此外,对于灾难恢复,您可以执行区域迁移。如果副本是跨区域副本,您可以执行故障切换到另一个区域;具体而言,您可以将副本提升为独立实例(在这种情况下,现有副本不会将该实例视为主实例)。

如需详细了解复制的工作原理,请参阅 Cloud SQL 中的复制

准备工作

如果要为此实例创建第一个副本,请确保该实例满足主实例的要求。了解详情

创建读取副本

以下是创建只读副本的步骤。

控制台

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 找到您要为其创建副本的实例,然后打开列表最右侧的 more actions 菜单。
  3. 选择创建只读副本

    如果您没有看到该选项,则表示此实例是副本;您无法创建副本的副本。

  4. 在该页面的自定义实例部分中,更新副本的设置。首先点击显示配置选项以显示设置组。然后,展开所需设置组以查看和自定义设置。所有选定选项的摘要会显示在右侧。自定义这些设置是可选操作。系统会为没有进行自定义的所有设置分配默认值。

    如需详细了解各项设置,请参阅实例设置简介页面。

    例如,如需允许其他 Google Cloud 服务(例如 BigQuery)访问 Cloud SQL 中的数据,并通过内部连接对此数据进行查询,请展开连接组,然后取消选中公共 IP 复选框。

  5. 点击创建副本

    Cloud SQL 会根据需要创建备份,并创建副本。随后,您将返回到主实例的实例页面。

gcloud

创建副本:

gcloud sql instances create REPLICA_NAME \
--master-instance-name=MASTER_INSTANCE_NAME

如果需要,您可以使用 --tier 参数指定不同的层级大小。

您可以使用 --region 参数指定不同区域。

如果主实例只有内部 IP 地址,并且您想要允许其他 Google Cloud 服务(例如 BigQuery)访问 Cloud SQL 中的数据,并通过内部连接对此数据进行查询,请在该命令中添加 --enable-google-private-path 参数。

您必须在与主实例相同的 VPC 网络中创建副本。您还可以在该 VPC 网络中指定 allocated-ip-range-name。如果未指定范围,则副本将在随机范围内创建。

Terraform

如需创建读取副本,请使用 Terraform 资源

resource "google_sql_database_instance" "read_replica" {
  name                 = "postgres-replica-instance-name"
  master_instance_name = google_sql_database_instance.primary.name
  region               = "europe-west4"
  database_version     = "POSTGRES_14"

  settings {
    tier              = "db-custom-2-7680"
    availability_type = "ZONAL"
    disk_size         = "100"
  }
  # set `deletion_protection` to true, will ensure that one cannot accidentally delete this instance by
  # use of Terraform whereas `deletion_protection_enabled` flag protects this instance at the GCP level.
  deletion_protection = false
}

REST v1

使用实例资源的 insert 方法创建读取副本。region 和 databaseVersion 属性必须与主实例的相同。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID
  • database-version:Enum 版本字符串(例如 POSTGRES_12)
  • primary-instance-name:主实例的名称
  • primary-instance-region:主实例的区域
  • replica-region:副本实例的区域
  • replica-name:副本实例的名称
  • machine-type:机器类型的枚举字符串。例如:“db-custom-1-3840”
  • private-network:您要添加或选择以创建专用连接的已获授权的网络。

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/v1/projects/project-id/instances

请求 JSON 正文:

{
  "masterInstanceName": "primary-instance-name",
  "project": "project-id",
  "databaseVersion": "database-version",
  "name": "replica-name",
  "region": "replica-region",
  "settings":
  {
    "tier": "machine-type",
    "settingsVersion": 0,
    "ipConfiguration": {
    object (IpConfiguration)
  },
  {
  "ipv4Enabled": false,
  "privateNetwork": private-network,
  "requireSsl": boolean,
  "authorizedNetworks": [
    {
      object (AclEntry)
    }
  ],
  "allocatedIpRange": string
    }
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

REST v1beta4

使用实例资源的 insert 方法创建读取副本。region 和 databaseVersion 属性必须与主实例的相同。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID
  • database-version:Enum 版本字符串(例如 POSTGRES_12)
  • primary-instance-name:主实例的名称
  • primary-instance-region:主实例的区域
  • replica-region:副本实例的区域
  • replica-name:副本实例的名称
  • machine-type:机器类型的枚举字符串。例如:“db-custom-1-3840”
  • private-network:您要添加或选择以创建专用连接的已获授权的网络。

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances

请求 JSON 正文:

{
  "masterInstanceName": "primary-instance-name",
  "project": "project-id",
  "databaseVersion": "database-version",
  "name": "replica-name",
  "region": "replica-region",
  "settings":
  {
    "tier": "machine-type",
    "settingsVersion": 0,

    "ipConfiguration": {
    object (IpConfiguration)
  },
  {
  "ipv4Enabled": false,
  "privateNetwork": private-network,
  "requireSsl": boolean,
  "authorizedNetworks": [
    {
      object (AclEntry)
    }
  ],
  "allocatedIpRange": string
    }

  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

创建启用了 Private Service Connect 的实例的读取副本

如需创建启用了 Private Service Connect 的实例的读取副本,请使用 gcloud CLI 或 API。您可以在与主实例相同的区域中创建此副本,也可以在与主实例不同的区域中创建此副本(跨区域读取副本)。

读取副本无法从使用其他连接类型的实例进行复制。例如,启用了 Private Service Connect 的实例只能从另一个 Private Service Connect 实例复制。它也无法从支持外部 IP 连接的实例或配置了专用服务访问通道的实例进行复制。

gcloud

如需创建实例的读取副本,请使用 gcloud sql instances create 命令:

gcloud sql instances create REPLICA_INSTANCE_NAME \
--master-instance-name=PRIMARY_INSTANCE_NAME \
--project=PROJECT_ID \
--region=REGION_NAME \
--enable-private-service-connect \
--allowed-psc-projects=ALLOWED_PROJECTS \
--availability-type=AVAILABILITY_TYPE \
--no-assign-ip

进行以下替换:

  • REPLICA_INSTANCE_NAME:副本实例的名称。
  • PRIMARY_INSTANCE_NAME:主实例的名称。
  • PROJECT_ID:包含实例的 Google Cloud 项目的 ID 或项目编号
  • REGION_NAME:副本实例的区域名称。
  • ALLOWED_PROJECTS:允许的项目 ID 或编号列表(以英文逗号分隔)。如果某个项目未包含在此列表中,您无法使用它来创建实例并为其启用 Private Service Connect。

    Cloud SQL 不会将主实例允许的项目复制到副本。对于每个副本,您必须创建一个 Private Service Connect 端点。如果您使用的是 Cloud SQL Auth 代理Cloud SQL 语言连接器,请为副本创建 DNS 区域DNS 记录

  • AVAILABILITY_TYPE:为实例启用高可用性。对于此参数,请指定以下值之一:
    • REGIONAL:启用高可用性,建议用于生产实例。实例会故障切换到所选区域内的另一个可用区。
    • ZONAL:不提供故障切换功能。此设置为默认值。

    如需详细了解如何为实例设置和移除高可用性,请参阅配置现有实例以实现高可用性为实例停用高可用性

REST v1

在使用任何请求数据之前,请先进行以下替换:

  • PRIMARY_INSTANCE_NAME:主实例的名称。
  • PROJECT_ID:包含实例的 Google Cloud 项目的 ID 或项目编号
  • REPLICA_INSTANCE_NAME:副本实例的名称。
  • REGION_NAME:副本实例的区域名称。
  • MACHINE_TYPE:实例的机器类型。
  • AVAILABILITY_TYPE:为实例启用高可用性。对于此参数,请指定以下值之一:
    • REGIONAL:启用高可用性,建议用于生产实例。实例会故障切换到所选区域内的另一个可用区。
    • ZONAL:不提供故障切换功能。此设置为默认值。

    如需详细了解如何为实例设置和移除高可用性,请参阅配置现有实例以实现高可用性为实例停用高可用性

  • ALLOWED_PROJECTS:允许的项目 ID 或编号列表(以英文逗号分隔)。如果某个项目未包含在此列表中,您无法使用它来创建实例并为其启用 Private Service Connect。

    Cloud SQL 不会将主实例允许的项目复制到副本。对于每个副本,您必须创建一个 Private Service Connect 端点。如果您使用的是 Cloud SQL Auth 代理Cloud SQL 语言连接器,则必须为副本创建 DNS 区域DNS 记录

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances

请求 JSON 正文:

{
  "masterInstanceName": "PRIMARY_INSTANCE_NAME",
  "project": "PROJECT_ID",
  "databaseVersion": "POSTGRES_13",
  "name": "REPLICA_INSTANCE_NAME",
  "region": "REGION_NAME",
  "kind": "sql#instance",
  "settings":
  {
    "tier": "MACHINE_TYPE",
    "availabilityType": "AVAILABILITY_TYPE",
    "settingsVersion": 0,
    "ipConfiguration": {
      "ipv4Enabled": false,
      "pscConfig": {
        "allowedConsumerProjects": [ALLOWED_PROJECTS],
        "pscEnabled": true
      }
    },
    "kind": "sql#settings",
    "pricingPlan": "PER_USE",
    "replicationType": "ASYNCHRONOUS",
    "tier": "MACHINE_TYPE"
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/REPLICA_INSTANCE_NAME",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "CREATE_REPLICA",
  "name": "OPERATION_ID",
  "targetId": "REPLICA_INSTANCE_NAME",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/operations/OPERATION_ID",
  "targetProject": "PROJECT_ID"
}

REST v1beta4

在使用任何请求数据之前,请先进行以下替换:

  • PRIMARY_INSTANCE_NAME:主实例的名称。
  • PROJECT_ID:包含实例的 Google Cloud 项目的 ID 或项目编号
  • REPLICA_INSTANCE_NAME:副本实例的名称。
  • REGION_NAME:副本实例的区域名称。
  • MACHINE_TYPE:实例的机器类型。
  • AVAILABILITY_TYPE:为实例启用高可用性。对于此参数,请指定以下值之一:
    • REGIONAL:启用高可用性,建议用于生产实例。实例会故障切换到所选区域内的另一个可用区。
    • ZONAL:不提供故障切换功能。此设置为默认值。

    如需详细了解如何为实例设置和移除高可用性,请参阅配置现有实例以实现高可用性为实例停用高可用性

  • ALLOWED_PROJECTS:允许的项目 ID 或编号列表(以英文逗号分隔)。如果某个项目未包含在此列表中,您无法使用它来创建实例并为其启用 Private Service Connect。

    Cloud SQL 不会将主实例允许的项目复制到副本。对于每个副本,您必须创建一个 Private Service Connect 端点。如果您使用的是 Cloud SQL Auth 代理Cloud SQL 语言连接器,则必须为副本创建 DNS 区域DNS 记录

HTTP 方法和网址:

PATCH https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances

请求 JSON 正文:

{
  "masterInstanceName": "PRIMARY_INSTANCE_NAME",
  "project": "PROJECT_ID",
  "databaseVersion": "POSTGRES_13",
  "name": "REPLICA_INSTANCE_NAME",
  "region": "REGION_NAME",
  "kind": "sql#instance",
  "settings":
  {
    "tier": "MACHINE_TYPE",
    "availabilityType": "AVAILABILITY_TYPE",
    "settingsVersion": 0,
    "ipConfiguration": {
      "ipv4Enabled": false,
      "pscConfig": {
        "allowedConsumerProjects": [ALLOWED_PROJECTS],
        "pscEnabled": true
      }
    },
    "kind": "sql#settings",
    "pricingPlan": "PER_USE",
    "replicationType": "ASYNCHRONOUS",
    "tier": "MACHINE_TYPE"
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/REPLICA_INSTANCE_NAME",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "CREATE_REPLICA",
  "name": "OPERATION_ID",
  "targetId": "REPLICA_INSTANCE_NAME",
  "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/operations/OPERATION_ID",
  "targetProject": "PROJECT_ID"
}

为 IAM 数据库身份验证配置只读副本

如果您在主实例上启用 cloudsql.iam_authentication 标志,则 Cloud SQL for PostgreSQL 会自动在读取副本上启用它。但是,如果您没有在主实例上启用此标志,则 Cloud SQL for PostgreSQL 不会在读取副本上启用它。您不能将副本用于 IAM 数据库身份验证。

如需为 IAM 数据库身份验证配置只读副本,请执行以下操作:

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 如需打开实例的概览页面,请点击实例名称。
  3. 在“配置”图块中,查找 cloudsql.iam_authentication 标志。如果列表中没有该标志,则无需在只读副本中启用该标志。如果列表包含该标志,则必须在读取副本中启用该标志。如果您需要在只读副本中启用该标志,请继续执行下一步。
  4. 从 SQL 导航菜单中选择副本
  5. 点击要修改的副本的名称。
  6. 点击修改
  7. 配置选项部分,展开标志
  8. 选择 + 添加项。
  9. 输入 cloudsql.iam_authentication 作为标志名称。确保为此标志选择开启
  10. 点击保存

创建级联副本

本部分介绍了如何创建和管理级联副本。如需了解级联副本的工作原理,请参阅级联副本

准备工作

主实例必须具有读取副本。如需详细了解如何创建主实例,请参阅创建读取副本

创建级联副本的步骤

控制台

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 单击副本的副本标签页,该副本将充当您要创建的副本的父级。
  3. 点击创建副本
  4. 创建读取副本页面上,更新实例 ID 和任何其他配置选项,包括名称、区域和可用区。
  5. 点击创建

    Cloud SQL 会创建一个副本。随后,您将返回到父级副本的实例页面。

  6. 对于要创建的每个新级联副本,请按照步骤 4-6 执行操作。

gcloud

  1. 使用 --master-instance-name 标志将主副本指定为主实例来创建新副本:

    gcloud sql instances create REPLICA_NAME \
          --master-instance-name=PARENT_REPLICA_NAME \
    替换以下内容:
    • REPLICA_NAME:您要创建的副本的唯一 ID
    • PARENT_REPLICA_NAME:父级副本的名称
  2. 创建副本后,您可以看到对主实例所做的更改已通过级联副本链中的所有副本进行复制。

curl

  1. 如需在父级副本下创建副本,请修改以下 JSON 代码示例并将其保存到名为 request.json 的文件中:

    {
      "masterInstanceName": "PARENT_REPLICA_NAME",
      "project": "PROJECT_ID",
      "name": "REPLICA_NAME",
      "region": "REPLICA_REGION",
      "settings":
        {
          "tier": "MACHINE_TYPE",
        }
    }
  2. 运行以下命令:
    curl -X POST
    -H "Authorization: Bearer "$(gcloud auth print-access-token)
    -H "Content-Type: application/json; charset=utf-8"
    -d @request.json
    "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances"

问题排查

问题 问题排查
创建时读取副本未开始复制。 日志文件中可能有更具体的错误信息。在 Cloud Logging 中查看日志以找到实际错误。
无法创建只读副本 - invalidFlagValue 错误 请求中的某个标志无效。它可能是您明确提供的标志,也可能是设置为默认值的标志。

首先,检查 max_connections 标志的值是否大于或等于主实例上的值。

如果 max_connections 标志设置正确,请在 Cloud Logging 中检查日志以找出实际错误。

无法创建只读副本 - 未知错误。 日志文件中可能有更具体的错误信息。在 Cloud Logging 中查看日志以找到实际错误。

如果错误为 set Service Networking service account as servicenetworking.serviceAgent role on consumer project,则停用 Service Networking API,然后重新启用。此操作会创建继续执行该过程所需的服务账号。

磁盘已满。 主实例磁盘大小可能在副本创建期间变满。 修改主实例以将其升级为更大的磁盘。
磁盘空间显著增加。 未主动用于跟踪数据的槽会使 PostgreSQL 无限期地保留在 WAL 分段中,从而导致磁盘空间无限增大。如果您使用 Cloud SQL 中的逻辑复制和解码功能,则系统会自动创建和丢弃复制槽。可通过查询 pg_replication_slots 系统视图并过滤 active 列检测到未使用的复制槽。您可以使用 pg_drop_replication_slot 命令丢弃未使用的槽以移除 WAL 分段。
副本实例占用的内存过多。 副本使用临时内存来缓存经常请求的读取操作,这可能会导致其占用的内存多于主实例。

重启副本实例以收回临时内存空间。

已停止复制。 已达到存储空间上限,且未启用存储空间自动扩容功能。

修改实例以启用 automatic storage increase

复制延迟一直很高。 写入负载过高,副本无法处理。当副本上的 SQL 线程无法与 IO 线程保持同步时,会发生复制延迟。某些类型的查询和工作负载会导致指定架构出现暂时性或永久性的高复制延迟。下面列出了复制延迟的部分常见原因:
  • 对副本的查询速度较慢。找到这些查询并进行修复。
  • 所有表都必须具有唯一键/主键。每次更新此类没有唯一键/主键的表都会导致对副本进行全表扫描。
  • 由于大量更新堆积在副本上,因此 DELETE ... WHERE field < 50000000 等查询会导致基于行的复制出现复制延迟。

以下是一些可行的解决方案:

  • 修改实例以增加副本的大小。
  • 减少数据库的负载。
  • 将读取流量发送到读取副本。
  • 将表编入索引。
  • 识别并修复速度缓慢的写入查询。
  • 重新创建副本。
在 PostgreSQL 9.6 中重建索引时出错。 您会收到来自 PostgreSQL 的错误,告知您需要重新构建特定索引。此操作只能在主实例上完成。如果您创建新的副本实例,则很快就会再次遇到同样的错误。在低于 10 的 PostgreSQL 版本中,哈希索引不会传播到副本

如果必须使用哈希索引,请升级到 PostgreSQL 10+。否则,如果您还想使用副本,请不要在 PostgreSQL 9.6 中使用哈希索引。

主实例上的查询始终运行。 创建副本后,查询 SELECT * from pg_stat_activity where state = 'active' and pid = XXXX and username = 'cloudsqlreplica' 应在主实例上连续运行。
副本创建失败并超时。 主实例上长时间运行的未提交事务可能会导致只读副本创建失败。

停止所有正在运行的查询后重新创建副本。

如果主实例和副本具有不同的 vCPU 大小,则可能存在查询性能问题,因为查询优化器会将 vCPU 大小考虑在内。

如需解决此问题,请完成以下步骤:

  1. 开启 log_duration 标志并将 log_statement 参数设置为 ddl。这样一来,您就可以同时获得针对数据库的查询和运行时间。但是,这可能会导致性能问题,具体取决于您的工作负载。
  2. 在主实例和读取副本上,针对查询运行 explain analyze
  3. 比较查询计划并检查差异。

如果是特定查询,请修改此查询。例如,您可以更改联接的顺序,以查看是否可以获得更好的性能。

后续步骤