本文档介绍了如何在 Cloud SQL 读取副本上创建、维护和监控二级索引。
如需了解托管式副本索引的工作原理,请参阅读取副本索引概览。
代管式副本索引
下表总结了创建、配置和监控代管式副本索引的工作流:
| 步骤 | 存储过程或数据库标志 | 如何执行步骤 |
|---|---|---|
| 创建索引定义 | CALL mysql.cloudsql_replica_idx_defn_create('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
此存储过程会返回索引定义的唯一整数标识符 |
主实例 |
| 将定义映射到群组 | CALL mysql.cloudsql_replica_idx_group_add(INDEX_DEFINITION_ID, 'GROUP_NAME');
|
主实例 |
| 将群组分配给副本 | 数据库标志:cloudsql_index_recreate_replica_group = GROUP_NAME |
读取副本实例 |
| 检查状态 | CALL mysql.cloudsql_replica_idx_show_status(); |
读取副本实例 |
| 审核错误 | CALL mysql.cloudsql_replica_idx_show_errors(); |
读取副本实例 |
每个存储过程调用都会执行一个 COMMIT 语句,该语句会最终确定当前会话中的更改。因此,使用这些存储过程执行的数据操纵语言 (DML) 语句无法在事务中回滚。
Cloud SQL 不支持更新或更改现有索引元数据。 如需修改代管式副本索引,您必须删除现有索引定义(或将其从副本组中移除),然后创建新的索引定义。如需了解详情,请参阅修改代管式副本索引。
所需的角色和权限
您必须使用分配了 cloudsqlsuperuser 角色的数据库用户账号来执行代管式副本索引的存储过程。
创建代管式副本索引
如需在读取副本上创建和维护代管式副本索引,请按以下步骤操作:
在主实例上创建索引定义:
在数据库主实例上调用
mysql.cloudsql_replica_idx_defn_create存储过程:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
替换以下内容:
INDEX_DEFINITION_NAME:索引定义的名称。CREATE_INDEX_STATEMENT:创建二级索引的 SQL 语句(例如CREATE INDEX idx_age ON university.students (age))。请注意,此语句必须带有架构前缀。
记下过程输出中返回的
idx_id(定义的唯一整数标识符)。Cloud SQL 会将此数据存储在mysql.cloudsql_replica_idx_defn中,您稍后可以通过查询此表来检索idx_id。将索引定义添加到副本组:
通过在主实例上调用
mysql.cloudsql_replica_idx_group_add,将索引定义映射到指定的副本组名称:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'GROUP_NAME');
替换以下内容:
INDEX_DEFINITION_ID:运行mysql.cloudsql_replica_idx_defn_create存储过程以创建二级索引时返回的唯一整数 ID。GROUP_NAME:副本组映射的名称(例如reporting_group)。GROUP_NAME是您可以选择的自定义名称。如果该群组不存在,Cloud SQL 会创建一个新群组。
Cloud SQL 会将这些数据存储在
mysql.cloudsql_replica_idx_group_map中,您稍后可以通过查询此表来检索群组映射。将该组分配给副本实例:
通过将数据库标志
cloudsql_index_recreate_replica_group设置为您的组名称(例如reporting_group),在读取副本上启用指定组。验证恢复进度:
连接到读取副本实例,然后检查索引的创建进度和状态。
查看正在进行的索引创建进度:
CALL mysql.cloudsql_replica_idx_show_status();查看失败的尝试和出错提示:
CALL mysql.cloudsql_replica_idx_show_errors();列出所有代管式索引的状态、重试详情和时长:
CALL mysql.cloudsql_replica_idx_show_all();
检查托管副本索引状态
如需查看索引操作状态,请连接到读取副本实例并查询 mysql.cloudsql_replica_idx_status 表:
SELECT * FROM mysql.cloudsql_replica_idx_status;
输出类似于以下内容:
+--------+----------------------------------------------------+--------+-----------+---------------------+---------------------+-------------+---------+--------------------+---------+ | idx_id | create_stmt | action | thread_id | start_time | end_time | retry_count | err_msg | comment_tag | status | +--------+----------------------------------------------------+--------+-----------+---------------------+---------------------+-------------+---------+--------------------+---------+ | 2 | CREATE INDEX t1_fname ON sampletest.t1(first_name) | CREATE | 8140 | 2026-08-26 10:52:13 | NULL | 0 | NULL | [SIC_4_1787741231] | RUNNING | | 4 | CREATE INDEX t2_lname ON sampletest.t2(last_name) | DROP | NULL | 2026-08-26 10:52:13 | 2026-08-26 10:53:15 | 0 | NULL | [SIC_4_1787741533] | DONE | | 5 | CREATE INDEX t1_lname ON sampletest.t1(last_name) | CREATE | 8142 | 2026-08-26 10:53:14 | NULL | 0 | NULL | [SIC_5_1787741594] | RUNNING | +--------+----------------------------------------------------+--------+-----------+---------------------+---------------------+-------------+---------+--------------------+---------+
Cloud SQL 会批量执行托管式副本索引维护。当 Cloud SQL 选取一组 CREATE 或 DROP 操作时,它会为每个索引创建一个 PENDING 状态条目,然后串行执行每个数据定义语言 (DDL) 语句。一个索引失败不会阻止队列中后续索引的执行。然后,Cloud SQL 会在大约 5 分钟后提取下一批。
如果索引创建失败,Cloud SQL 会将状态标记为 FAILED,并在 1 小时后自动重试该操作。
mysql.cloudsql_replica_idx_status 表包含所有索引操作状态条目,并包含以下列:
idx_id:索引定义的唯一整数标识符。create_stmt:CREATE INDEXSQL 语句。action:正在执行的操作(CREATE或DROP)。thread_id:执行操作的 MySQL 线程 ID。start_time:操作开始时的时间戳。end_time:操作完成时的时间戳。retry_count:操作的重试次数。Cloud SQL 会在一小时后重试失败的索引创建操作。err_msg:上次失败操作的出错提示。comment_tag:附加到索引注释前面的[SIC_X_Y]标记。此标记仅用于内部管理,没有任何功能。status:操作的当前状态:PENDING:索引操作已添加到队列中。RUNNING:索引操作已开始执行。DONE:索引操作已成功完成。FAILED:索引操作失败。Cloud SQL 会在一小时后重试失败的索引创建操作。
舍弃代管式副本索引
如需从副本组中移除索引或完全删除索引定义,请在主实例上调用相应的存储过程:
从副本组中移除索引定义:
在主实例上调用
mysql.cloudsql_replica_idx_group_drop:CALL mysql.cloudsql_replica_idx_group_drop (INDEX_DEFINITION_ID, 'GROUP_NAME');
替换以下内容:
INDEX_DEFINITION_ID:创建二级索引定义时返回的唯一整数 ID。GROUP_NAME:副本组映射的名称(例如reporting_group)。
删除索引定义:
在主实例上调用
mysql.cloudsql_replica_idx_defn_drop:CALL mysql.cloudsql_replica_idx_defn_drop (INDEX_DEFINITION_ID);
替换以下内容:
INDEX_DEFINITION_ID:要删除的索引定义的唯一整数 ID。
如需详细了解存储过程,请参阅代管式副本索引存储过程。
修改托管式副本索引
Cloud SQL 不支持更新或更改现有索引元数据。 您无法直接修改现有索引定义或其 SQL 语句。
如需修改代管式副本索引(例如,更改已编入索引的列或索引选项),您必须移除或删除现有索引定义,然后创建新的索引定义。
如需修改代管式副本索引,请按以下步骤操作:
移除或删除主实例上的现有索引定义:
如需从副本组中移除索引定义,请调用
mysql.cloudsql_replica_idx_group_drop:CALL mysql.cloudsql_replica_idx_group_drop (INDEX_DEFINITION_ID, 'GROUP_NAME');
如需彻底删除索引定义,请调用
mysql.cloudsql_replica_idx_defn_drop:CALL mysql.cloudsql_replica_idx_defn_drop (INDEX_DEFINITION_ID);
替换以下内容:
INDEX_DEFINITION_ID:要移除或删除的索引定义的唯一整数 ID。GROUP_NAME:副本组映射的名称(例如reporting_group)。
在主实例上创建新的索引定义:
使用更新后的索引语句调用
mysql.cloudsql_replica_idx_defn_create:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
替换以下内容:
INDEX_DEFINITION_NAME:新索引定义的名称。CREATE_INDEX_STATEMENT:用于创建二级索引的更新后的 SQL 语句(例如CREATE INDEX idx_age ON university.students (age, name))。
记下存储过程输出中返回的新
idx_id。将新索引定义映射到副本组:
在主实例上调用
mysql.cloudsql_replica_idx_group_add:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'GROUP_NAME');
替换以下内容:
INDEX_DEFINITION_ID:第 2 步中返回的新唯一整数 ID。GROUP_NAME:副本组映射的名称(例如reporting_group)。
将新索引定义映射到副本组后,后台维护进程会从读取副本中删除现有索引,然后使用更新后的定义在副本上创建新索引。
用于代管式副本索引的数据库配置标志
您可以使用以下全局数据库标志动态自定义托管副本索引行为:
cloudsql_index_recreate_enable:启用或停用重新创建过程。默认情况下,此标志会设置为on。将该标志设置为off会立即终止正在进行的索引维护操作。cloudsql_index_recreate_replica_group:副本的指定副本组名称(默认值为NULL)。一个副本一次只能分配给一个副本组。副本会构建映射到此副本组名称的所有索引。
自管理副本索引
Cloud SQL 在 mysql 架构中包含了两个存储过程,您可以使用它们在 MySQL 读取副本上添加和删除二级索引。请注意,虽然这些存储过程可以在主源实例上运行,但它们是为读取副本设计的。
如果重新创建副本,这些索引不会保留。
- mysql.addSecondaryIdxOnReplica
- 在数据库上添加二级索引。此存储过程是 CREATE INDEX DDL 语句的封装容器。
参数:
idxType:要创建的索引类型。例如,传递UNIQUE以创建唯一索引。idxName:索引的名称。tableName:表的名称,格式为schema.name。idxDefinition:索引的定义。请勿添加外括号。idxOption:在创建索引时要传递的任何其他选项。例如,在 MySQL 8.0 中,您可以为不可见索引传递INVISIBLE选项。
语法:
mysql.addSecondaryIdxOnReplica(idxType, idxName, tableName, idxDefinition, idxOption) - mysql.dropSecondaryIdxOnReplica
- 删除数据库上的二级索引。此存储过程是 DROP INDEX DDL 语句的封装容器。
参数:
idxName:索引的名称。tableName:表的名称,格式为schema.name。idxOption:删除索引时要传递的任何其他选项。例如,算法选项,如INPLACE。
语法:
mysql.dropSecondaryIdxOnReplica(idxName, tableName, idxOption)
对于 idxType 和 idxOption 参数,请参阅 Cloud SQL 实例上运行的 MySQL 主要版本的文档。
示例
本部分提供了有关如何正确或错误地添加或删除自行管理的副本索引的示例。
正确用法
以下是这些过程的一些示例调用。假设您有一个表,其定义如下:
CREATE TABLE sampletest.t1(
id int(10) unsigned NOT NULL AUTO_INCREMENT,
first_name varchar(64) NOT NULL,
last_name varchar(64) NOT NULL,
license_id int NOT NULL,
PRIMARY KEY (id),
KEY idx_fname (first_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
如果您想在 first_name 和 last_name 列上创建名为 t1_fname_lname 的常规索引,请运行以下语句:
CALL mysql.addSecondaryIdxOnReplica('', 't1_fname_lname', 'sampletest.t1', 'first_name, last_name', '')
如果您还想在 license_id 列上创建名为 t1_license_id 的唯一索引,并添加注释“unique license ID”,请运行以下语句:
CALL mysql.addSecondaryIdxOnReplica('unique', 't1_license_id', 'sampletest.t1', 'license_id', 'comment "unique license ID"')
如果要删除 t1_fname_lname 索引,请运行以下语句:
CALL mysql.dropSecondaryIdxOnReplica('t1_fname_lname', 'sampletest.t1', '')
错误用法
由于 idxDefinition 参数中存在外括号,因此以下在 first_name 和 last_name 列上创建索引的尝试失败:
CALL mysql.addSecondaryIdxOnReplica('', 't1_extra_parenthesis', 'sampletest.t1', '(first_name, last_name)', '')
您只能在客户创建的表上添加索引。以下尝试在 mysql.servers 表的 host 列上创建索引的操作失败:
CALL mysql.addSecondaryIdxOnReplica('', 'idx_invalid', 'mysql.servers', 'host', '')
您只能使用 dropSecondaryIdxOnReplica 过程删除之前使用 addSecondaryIdxOnReplica 过程创建的索引。例如,以下用于删除现有 idx_fname 索引的调用会失败:
CALL mysql.dropSecondaryIdxOnReplica('idx_fname', 'sampletest.t1', '')
这些过程调用中的 SQL 注入会失败。例如,以下带有注释序列的 SQL 注入会失败:
CALL mysql.addSecondaryIdxOnReplica("user 'a'@'%' --", 'idx_fname', 'sampletest.t1', 'first_name', '')
同样,以下使用定界符的 SQL 注入尝试也会失败:
CALL mysql.addSecondaryIdxOnReplica('', 'idx_fname', 'sampletest.t1', 'first_name', ';flush status')
从自行管理的副本索引迁移到托管式副本索引
虽然托管式副本索引和自行管理的副本索引可以共存于同一实例中,但您可以迁移到托管式副本索引。
如需从自行管理的副本索引迁移到托管式副本索引,请按以下步骤操作:
在主实例上注册索引定义:
针对每个二级索引,在主实例上调用
mysql.cloudsql_replica_idx_defn_create:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE INDEX INDEX_NAME ON DATABASE.TABLE (COLUMNS)');
记下过程输出中返回的
idx_id(定义的唯一整数标识符)。将索引定义添加到副本组:
通过在主实例上调用
mysql.cloudsql_replica_idx_group_add,将索引定义映射到指定的副本组名称:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'REPLICA_GROUP');
在读取副本上配置副本组标志:
在读取副本实例上设置
cloudsql_index_recreate_replica_group数据库标志,以定位到组名称:gcloud sql instances patch REPLICA_INSTANCE_NAME \ --database-flags=EXISTING_FLAGS,cloudsql_index_recreate_replica_group=REPLICA_GROUP
确保
cloudsql_index_recreate_replica_group数据库标志中提供的群组名称与mysql.cloudsql_replica_idx_group_add中指定的群组名称完全一致。验证或转换现有索引:
由于索引已存在于读取副本中,因此当后台进程尝试创建索引时,您可能会在
mysql.cloudsql_replica_idx_status中看到状态为FAILED的错误。您可以选择以下方法之一:- 等待副本重新创建:您可以放心地忽略状态表中的
FAILED状态。在副本重新创建事件后,Cloud SQL 会使用代管式副本索引方法自动重新创建二级索引。 立即转换:如果您希望 Cloud SQL 立即管理索引,而无需等待副本重新创建,请连接到读取副本,并使用
mysql.dropSecondaryIdxOnReplica存储过程移除自行管理的索引:CALL mysql.dropSecondaryIdxOnReplica('INDEX_NAME', 'DATABASE.TABLE', '');
在下一个后台维护周期(大约每五分钟一次)期间,Cloud SQL 会自动重新创建并跟踪代管式副本索引。
- 等待副本重新创建:您可以放心地忽略状态表中的
排查副本索引问题
如需排查副本索引问题,请验证以下各项:
验证是否已为副本实例启用代管式副本索引:
如果您使用的是代管式副本索引,请确保在读取副本上将
cloudsql_index_recreate_enable数据库标志设置为on。如需详细了解如何配置数据库标志,请参阅配置数据库标志。
检查操作状态和错误:
连接到读取副本并查询
mysql.cloudsql_replica_idx_status或运行CALL mysql.cloudsql_replica_idx_show_errors();,以查看任何失败操作的错误消息。一个索引失败不会阻止队列中后续索引的执行。
后续步骤
- 详细了解读取副本索引。
- 了解如何管理只读副本。
- 了解如何创建只读副本。
- 了解 Cloud SQL 中的复制。
- 了解复制延迟时间。
- 了解如何配置数据库标志。
- 了解 Cloud SQL for MySQL 的存储过程。
- 了解高级灾难恢复 (DR)。
- 了解如何使用 MySQL 客户端进行连接。