This document describes how to create, maintain, and monitor secondary indexes on Cloud SQL read replicas.
For conceptual information about how managed replica indexes work, see Read replica indexes overview.
Managed replica indexes
The following table summarizes the workflow for creating, configuring, and monitoring managed replica indexes:
| Step | Stored procedure or database flag | Where to perform the step |
|---|---|---|
| Create index definition | CALL mysql.cloudsql_replica_idx_defn_create('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
This stored procedure returns a unique integer identifier for
the index definition, |
Primary instance |
| Map definition to group | CALL mysql.cloudsql_replica_idx_group_add(INDEX_DEFINITION_ID, 'GROUP_NAME');
|
Primary instance |
| Assign group to replica | Database flag: cloudsql_index_recreate_replica_group = GROUP_NAME |
Read replica instance |
| Check status | CALL mysql.cloudsql_replica_idx_show_status(); |
Read replica instance |
| Audit errors | CALL mysql.cloudsql_replica_idx_show_errors(); |
Read replica instance |
Each stored procedure call executes a COMMIT statement that finalizes the
changes in your current session. As a result, data manipulation language (DML)
statements executed using these stored procedures can't be rolled back within a
transaction.
Cloud SQL doesn't support updating or altering existing index metadata. To modify a managed replica index, you must drop the existing index definition (or remove it from the replica group) and create a new index definition. For more information, see Modify managed replica indexes.
Required role and privileges
You must use a database user account that's assigned the
cloudsqlsuperuser role to execute stored procedures for
managed replica indexes.
Create managed replica indexes
To create and maintain managed replica indexes on your read replicas, follow these steps:
Create an index definition on the primary instance:
Call the
mysql.cloudsql_replica_idx_defn_createstored procedure on your database primary instance:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
Replace the following:
INDEX_DEFINITION_NAME: the name of the index definition.CREATE_INDEX_STATEMENT: the SQL statement that creates the secondary index (for example,CREATE INDEX idx_age ON university.students (age)). Note that this statement must be schema-prefixed.
Take note of the returned
idx_id(a unique integer identifier for the definition) from the procedure output. Cloud SQL stores this data inmysql.cloudsql_replica_idx_defn, and you can retrieve theidx_idlater by querying this table.Add the index definition to a replica group:
Map the index definition to a designated replica group name by calling
mysql.cloudsql_replica_idx_group_addon the primary instance:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'GROUP_NAME');
Replace the following:
INDEX_DEFINITION_ID: the unique integer ID returned when you ran themysql.cloudsql_replica_idx_defn_createstored procedure to create the secondary index.GROUP_NAME: the name of the replica group mapping (for example,reporting_group). TheGROUP_NAMEis a custom name that you can select. If that group doesn't exist, then Cloud SQL creates a new one.
Cloud SQL stores this data in
mysql.cloudsql_replica_idx_group_map, and you can retrieve group mappings later by querying this table.Assign the group to your replica instance:
Enable the designated group on your read replica by setting the database flag
cloudsql_index_recreate_replica_groupto your group name (for example,reporting_group).Verify the restoration progress:
Connect to your read replica instance, and check the creation progress and status of your indexes.
Check ongoing index creation progress:
CALL mysql.cloudsql_replica_idx_show_status();Check failed attempts and error messages:
CALL mysql.cloudsql_replica_idx_show_errors();List the status, retry details, and durations for all managed indexes:
CALL mysql.cloudsql_replica_idx_show_all();
Check managed replica index status
To check index operation status, connect to your read replica instance and query
the mysql.cloudsql_replica_idx_status table:
SELECT * FROM mysql.cloudsql_replica_idx_status;
The output is similar to the following:
+--------+----------------------------------------------------+--------+-----------+---------------------+---------------------+-------------+---------+--------------------+---------+ | 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 performs managed replica index maintenance in batches. When
Cloud SQL picks up a group of CREATE or DROP actions, it
creates a PENDING status entry for each index, and then serially
executes each data definition language (DDL) statement. A failure on one
index doesn't block the execution of subsequent indexes in the queue.
Cloud SQL then picks up the next batch after approximately
five minutes.
If an index creation fails, then Cloud SQL marks the status
as FAILED and automatically retries the operation after one hour.
The mysql.cloudsql_replica_idx_status table contains all index operation
status entries and includes the following columns:
idx_id: the unique integer identifier for the index definition.create_stmt: theCREATE INDEXSQL statement.action: the operation being performed (CREATEorDROP).thread_id: the MySQL thread ID executing the operation.start_time: the timestamp when the operation started.end_time: the timestamp when the operation completed.retry_count: the number of retry attempts for the operation. Cloud SQL retries failed index creations after one hour.err_msg: the error message of the last failed operation.comment_tag: the[SIC_X_Y]tag prepended to the index comment. This tag is used solely for internal management and has no functionality.status: the current status of the operation:PENDING: the index operation has been added to the queue.RUNNING: the index operation execution has started.DONE: the index operation completed successfully.FAILED: the index operation failed. Cloud SQL retries failed index creations after one hour.
Drop managed replica indexes
To remove an index from a replica group or delete an index definition entirely, call the corresponding stored procedure on your primary instance:
Remove an index definition from a replica group:
Call
mysql.cloudsql_replica_idx_group_dropon the primary instance:CALL mysql.cloudsql_replica_idx_group_drop (INDEX_DEFINITION_ID, 'GROUP_NAME');
Replace the following:
INDEX_DEFINITION_ID: the unique integer ID returned when you created the secondary index definition.GROUP_NAME: the name of the replica group mapping (for example,reporting_group).
Delete an index definition:
Call
mysql.cloudsql_replica_idx_defn_dropon the primary instance:CALL mysql.cloudsql_replica_idx_defn_drop (INDEX_DEFINITION_ID);
Replace the following:
INDEX_DEFINITION_ID: the unique integer ID of the index definition to delete.
For more information about stored procedures, see Managed replica indexes stored procedures.
Modify managed replica indexes
Cloud SQL doesn't support updating or altering existing index metadata. You can't modify an existing index definition or its SQL statement directly.
To modify a managed replica index (for example, to change indexed columns or index options), you must remove or delete the existing index definition, and then create a new index definition.
To modify a managed replica index, follow these steps:
Remove or delete the existing index definition on the primary instance:
To remove the index definition from a replica group, call
mysql.cloudsql_replica_idx_group_drop:CALL mysql.cloudsql_replica_idx_group_drop (INDEX_DEFINITION_ID, 'GROUP_NAME');
To delete the index definition completely, call
mysql.cloudsql_replica_idx_defn_drop:CALL mysql.cloudsql_replica_idx_defn_drop (INDEX_DEFINITION_ID);
Replace the following:
INDEX_DEFINITION_ID: the unique integer ID of the index definition to remove or delete.GROUP_NAME: the name of the replica group mapping (for example,reporting_group).
Create a new index definition on the primary instance:
Call
mysql.cloudsql_replica_idx_defn_createwith the updated index statement:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE_INDEX_STATEMENT');
Replace the following:
INDEX_DEFINITION_NAME: the name of the new index definition.CREATE_INDEX_STATEMENT: the updated SQL statement that creates the secondary index (for example,CREATE INDEX idx_age ON university.students (age, name)).
Take note of the new
idx_idreturned in the stored procedure output.Map the new index definition to the replica group:
Call
mysql.cloudsql_replica_idx_group_addon the primary instance:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'GROUP_NAME');
Replace the following:
INDEX_DEFINITION_ID: the new unique integer ID returned in step 2.GROUP_NAME: the name of the replica group mapping (for example,reporting_group).
After you map the new index definition to the replica group, the background maintenance process drops the existing index from the read replica and then creates the new index on the replica using the updated definition.
Database configuration flags for managed replica indexes
You can customize managed replica index behavior dynamically by using the following global database flags:
cloudsql_index_recreate_enable: enables or disables the re-creation process. By default, the flag is set toon. Setting the flag tooffimmediately terminates ongoing index maintenance operations.cloudsql_index_recreate_replica_group: designated replica group name for the replica (default isNULL). A replica can be assigned to only one replica group at a time. Replicas build all indexes mapped to this replica group name.
Self-managed replica indexes
Cloud SQL includes two stored procedures in the mysql schema that you
can use to add and drop secondary indexes on a MySQL read replica. Note that
while these stored procedures can run on a primary source instance, they're
designed for read replicas.
These indexes don't persist if the replica is re-created.
- mysql.addSecondaryIdxOnReplica
- Adds a secondary index on the database. This stored procedure is a
wrapper for the
CREATE INDEX
DDL statement.
Parameters:
idxType: type of index to create. For example, passUNIQUEto create a unique index.idxName: name of the index.tableName: name of the table in the format ofschema.name.idxDefinition: definition of the index. Don't include the outer parentheses.idxOption: any additional options to pass on index creation. For example, in MySQL 8.0, you can pass theINVISIBLEoption for an invisible index.
Syntax:
mysql.addSecondaryIdxOnReplica(idxType, idxName, tableName, idxDefinition, idxOption) - mysql.dropSecondaryIdxOnReplica
- Drops a secondary index on the database. This stored procedure is a
wrapper for the
DROP INDEX
DDL statement.
Parameters:
idxName: name of the index.tableName: name of the table in the format ofschema.name.idxOption: any additional options to pass when dropping an index. For example, an algorithm option such asINPLACE.
Syntax:
mysql.dropSecondaryIdxOnReplica(idxName, tableName, idxOption)
For the idxType and idxOption parameters, consult the documentation for the
major version of MySQL running on the Cloud SQL instance.
Examples
This section provides examples of how you might correctly or incorrectly add or drop self-managed replica indexes.
Correct usage
Here are some example invocations of the procedures. Suppose you have a table with the following definition:
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
If you want to create a regular index named t1_fname_lname on the
first_name and last_name columns, run the following statement:
CALL mysql.addSecondaryIdxOnReplica('', 't1_fname_lname', 'sampletest.t1', 'first_name, last_name', '')
If you also want to create a unique index named t1_license_id on the
license_id column with the comment "unique license ID", run the
following statement:
CALL mysql.addSecondaryIdxOnReplica('unique', 't1_license_id', 'sampletest.t1', 'license_id', 'comment "unique license ID"')
If you want to drop the t1_fname_lname index, run the following statement:
CALL mysql.dropSecondaryIdxOnReplica('t1_fname_lname', 'sampletest.t1', '')
Incorrect usage
The following attempt to create an index on the first_name and last_name
columns fails due to the outer parentheses in the idxDefinition parameter:
CALL mysql.addSecondaryIdxOnReplica('', 't1_extra_parenthesis', 'sampletest.t1', '(first_name, last_name)', '')
You can only add indexes on customer-created tables. The following attempt to
create an index on the host column of the mysql.servers table fails:
CALL mysql.addSecondaryIdxOnReplica('', 'idx_invalid', 'mysql.servers', 'host', '')
You can only use the dropSecondaryIdxOnReplica procedure to drop indexes
previously created using the addSecondaryIdxOnReplica procedure. For example,
the following call to drop the existing idx_fname index fails:
CALL mysql.dropSecondaryIdxOnReplica('idx_fname', 'sampletest.t1', '')
SQL injection in these procedure calls fails. For example, the following SQL injection with a comment sequence fails:
CALL mysql.addSecondaryIdxOnReplica("user 'a'@'%' --", 'idx_fname', 'sampletest.t1', 'first_name', '')
Similarly, this SQL injection attempt with a delimiter fails:
CALL mysql.addSecondaryIdxOnReplica('', 'idx_fname', 'sampletest.t1', 'first_name', ';flush status')
Migrate from self-managed to managed replica indexes
Although both managed replica indexes and self-managed replica indexes can coexist on the same instance, you can migrate to managed replica indexes.
To migrate from self-managed to managed replica indexes, follow these steps:
Register index definitions on the primary instance:
Call
mysql.cloudsql_replica_idx_defn_createon your primary instance for each secondary index:CALL mysql.cloudsql_replica_idx_defn_create ('INDEX_DEFINITION_NAME', 'CREATE INDEX INDEX_NAME ON DATABASE.TABLE (COLUMNS)');
Take note of the returned
idx_id(a unique integer identifier for the definition) from the procedure output.Add the index definition to a replica group:
Map the index definition to a designated replica group name by calling
mysql.cloudsql_replica_idx_group_addon the primary instance:CALL mysql.cloudsql_replica_idx_group_add (INDEX_DEFINITION_ID, 'REPLICA_GROUP');
Configure the replica group flag on the read replica:
Set the
cloudsql_index_recreate_replica_groupdatabase flag on your read replica instance to target the group name:gcloud sql instances patch REPLICA_INSTANCE_NAME \ --database-flags=EXISTING_FLAGS,cloudsql_index_recreate_replica_group=REPLICA_GROUP
Make sure that the group name provided in the
cloudsql_index_recreate_replica_groupdatabase flag matches the group name specified inmysql.cloudsql_replica_idx_group_addexactly.Verify or transition the existing indexes:
Because the index already exists on the read replica, you might see errors with a
FAILEDstatus inmysql.cloudsql_replica_idx_statuswhen the background process attempts to create the index. You can choose one of the following approaches:- Wait for replica re-creation: you can safely ignore the
FAILEDstatus in the status table. Cloud SQL automatically re-creates the secondary index using the managed replica index method after a replica re-creation event. Transition immediately: if you want Cloud SQL to manage the index immediately without waiting for a replica re-creation, connect to the read replica and remove the self-managed index by using the
mysql.dropSecondaryIdxOnReplicastored procedure:CALL mysql.dropSecondaryIdxOnReplica('INDEX_NAME', 'DATABASE.TABLE', '');
During the next background maintenance cycle (approximately every five minutes), Cloud SQL automatically re-creates and tracks the managed replica index.
- Wait for replica re-creation: you can safely ignore the
Troubleshoot replica indexes
To troubleshoot replica indexes, verify the following:
Verify that managed replica indexes are enabled for the replica instance:
If you're using managed replica indexes, make sure that the
cloudsql_index_recreate_enabledatabase flag is set toonon the read replica.For more information about configuring database flags, see Configure database flags.
Check operation status and errors:
Connect to the read replica and query
mysql.cloudsql_replica_idx_statusor runCALL mysql.cloudsql_replica_idx_show_errors();to view error messages for any failed operations. A failure on one index doesn't block the execution of subsequent indexes in the queue.
What's next
- Learn more about read replica indexes.
- Learn how to manage read replicas.
- Learn how to create read replicas.
- Learn about replication in Cloud SQL.
- Learn about replication lag.
- Learn how to configure database flags.
- Learn about stored procedures for Cloud SQL for MySQL.
- Learn about advanced disaster recovery (DR).
- Learn how to connect using a MySQL client.