{
  "schema_version": 2,
  "id": "integrate/redis-data-integration/data-pipelines/prepare-dbs/gcp-cloud-sql-mysql",
  "title": "Prepare Google Cloud SQL for MySQL for RDI",
  "url": "https://redis.io/docs/latest/integrate/redis-data-integration/2.0.0/data-pipelines/prepare-dbs/gcp-cloud-sql-mysql/",
  "summary": "Prepare a Google Cloud SQL for MySQL database to work with RDI",
  "content": "\n[Google Cloud SQL for MySQL](https://cloud.google.com/sql/docs/mysql) is a\nmanaged MySQL service on Google Cloud. RDI captures changes from an instance of Cloud SQL\nfor MySQL through its binary log (binlog), in the same way it would for a\nself-managed MySQL server.\n\n\u003e [!NOTE]\n\u003e This page describes Cloud SQL for MySQL configured for a self-managed RDI\n\u003e deployment (VM or Kubernetes). The integration was validated with RDI 2.0.0\n\u003e and Cloud SQL for MySQL 8.0 on a Regional (high availability) instance, using\n\u003e a public IP connection with encrypted connections enforced. See\n\u003e [RDI in Redis Cloud](https://redis.io/docs/latest/integrate/redis-data-integration#rdi-in-redis-cloud)\n\u003e for the source databases that the managed service supports.\n\nCloud SQL differs from a self-managed MySQL source in the following ways:\n\n- You can't edit the MySQL configuration file. You enable binary logging as an\n  instance setting and set other server variables as Cloud SQL\n  [database flags](https://cloud.google.com/sql/docs/mysql/flags).\n- Cloud SQL already sets `binlog_format` to `ROW` and enables GTIDs, so you don't\n  need to change them.\n- Cloud SQL can enforce encrypted connections. If it does, you must configure RDI\n  to connect over TLS (Transport Layer Security), or the connection fails with an\n  error that looks like a credentials problem.\n- On a Regional instance, a failover moves the primary to another zone. RDI\n  reconnects automatically, as described in\n  [Failover on Regional instances](#failover-on-regional-instances).\n\nThe following checklist summarizes the steps to prepare Cloud SQL for MySQL to work with RDI:\n\n```checklist {id=\"cloudsqlmysqllist\"}\n- [ ] [Enable binary logging](#1-enable-binary-logging)\n- [ ] [Set the binlog row image](#2-set-the-binlog-row-image)\n- [ ] [Check the binlog settings](#3-check-the-binlog-settings)\n- [ ] [Allow network access from RDI](#4-allow-network-access-from-rdi)\n- [ ] [Create a CDC user](#5-create-a-cdc-user)\n- [ ] [Configure RDI](#6-configure-rdi)\n```\n\n## 1. Enable binary logging\n\nRDI reads changes from the MySQL binlog, which Cloud SQL only writes when binary\nlogging is enabled. Binary logging requires automated backups.\n\nTo enable binary logging when you create an instance, pass `--enable-bin-log` to\n[`gcloud sql instances create`](https://cloud.google.com/sdk/gcloud/reference/sql/instances/create).\nThe following example shows how to do this and also sets the binlog row image flag from\n[step 2](#2-set-the-binlog-row-image) and enforces encrypted connections:\n\n```bash\ngcloud sql instances create \u003cinstance-name\u003e \\\n  --database-version=MYSQL_8_0 \\\n  --region=\u003cregion\u003e \\\n  --tier=\u003cmachine-tier\u003e \\\n  --availability-type=REGIONAL \\\n  --enable-bin-log \\\n  --database-flags=binlog_row_image=full \\\n  --ssl-mode=ENCRYPTED_ONLY\n```\n\nTo enable binary logging on an existing instance, run:\n\n```bash\ngcloud sql instances patch \u003cinstance-name\u003e --enable-bin-log\n```\n\nIn the Google Cloud console, binary logging is part of\n[point-in-time recovery](https://cloud.google.com/sql/docs/mysql/backup-recovery/pitr).\nYou must therefore enable point-in-time recovery for the instance to enable binary logging.\n\n## 2. Set the binlog row image\n\nRDI requires the full row image. Set the `binlog_row_image` database flag to\n`full`:\n\n```bash\ngcloud sql instances patch \u003cinstance-name\u003e --database-flags=binlog_row_image=full\n```\n\nThe flag value must be lowercase. Cloud SQL rejects `binlog_row_image=FULL` (that is with `FULL` in uppercase)\nwith the error `FULL was not an expected string`. MySQL reports the value as\n`FULL` after you set it.\n\n\u003e [!WARNING]\n\u003e The `--database-flags` option replaces all the database flags that are\n\u003e currently set on the instance. If the instance already has other flags, include\n\u003e them in the same command. Changing database flags can restart the instance. See\n\u003e [Configure database flags](https://cloud.google.com/sql/docs/mysql/flags) for\n\u003e details.\n\nYou can also set the flag in the Google Cloud console, in the **Flags** section\nwhen you edit the instance.\n\n## 3. Check the binlog settings\n\nConnect to the instance with the\n[MySQL CLI client](https://dev.mysql.com/doc/refman/8.0/en/mysql.html) and run\nthe following query:\n\n```sql\nSHOW GLOBAL VARIABLES WHERE Variable_name IN\n  ('log_bin', 'binlog_format', 'binlog_row_image', 'gtid_mode',\n   'binlog_row_value_options');\n```\n\nCheck that the result has the following values:\n\n| Variable | Value |\n| :-- | :-- |\n| `log_bin` | `ON` |\n| `binlog_format` | `ROW` |\n| `binlog_row_image` | `FULL` |\n| `gtid_mode` | `ON` |\n| `binlog_row_value_options` | Empty (not `PARTIAL_JSON`) |\n\nSee\n[Check `binlog_row_value_options`](https://redis.io/docs/latest/integrate/redis-data-integration/data-pipelines/prepare-dbs/my-sql-mariadb#6-check-binlog_row_value_options)\nto learn why `PARTIAL_JSON` is a problem.\n\n## 4. Allow network access from RDI\n\nIf RDI connects to the instance's public IP address, add the public egress IP\naddress of the RDI host or Kubernetes cluster to the instance's\n[authorized networks](https://cloud.google.com/sql/docs/mysql/authorize-networks).\nUse a `/32` CIDR for an individual IPv4 address:\n\n```bash\ngcloud sql instances patch \u003cinstance-name\u003e --authorized-networks=\u003crdi-egress-ip\u003e/32\n```\n\nThe `--authorized-networks` option replaces the existing list, so include any\nnetworks that are already authorized.\n\n## 5. Create a CDC user\n\nThe Debezium connector needs a MySQL user account to connect to the instance.\nCreate the user with\n[`gcloud sql users create`](https://cloud.google.com/sdk/gcloud/reference/sql/users/create)\nand set `--host` explicitly:\n\n```bash\ngcloud sql users create \u003cusername\u003e \\\n  --instance=\u003cinstance-name\u003e \\\n  --host=% \\\n  --password=\u003cpassword\u003e\n```\n\nThe value of `%` for `host` lets the user connect from any client address. To restrict the user\nto the RDI host, use that host's IP address instead.\n\nThen connect to the instance as an administrator user, such as `root`, and grant\nthe user the permissions that RDI needs. Use the same host value that you used\nto create the user:\n\n```sql\nGRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO '\u003cusername\u003e'@'%';\nFLUSH PRIVILEGES;\n```\n\nNote that the `GRANT` statement might fail with\n`ERROR 1410 (42000): You are not allowed to create a user with GRANT`. This happens when the user\ndoesn't exist with that host, since Cloud SQL's administrator user can't create a user\nimplicitly with `GRANT`. Check the user's host with\n`gcloud sql users list --instance=\u003cinstance-name\u003e`, and either grant to the host\nshown there or recreate the user with the `--host` value you want.\n\n## 6. Configure RDI\n\nStore the CDC user's credentials as RDI secrets. Pass the source name with\n`--db` (the source in the following example is named `mysql`):\n\n```bash\nredis-di set-secret USERNAME --db mysql \u003cusername\u003e\nredis-di set-secret PASSWORD --db mysql \u003cpassword\u003e\n```\n\nAdd a MySQL source to `config.yaml`. If the instance enforces encrypted\nconnections, set `database.ssl.mode` to `required` (or a stricter mode) in the\nsource's `advanced.source` section:\n\n```yaml\nsources:\n  mysql:\n    type: cdc\n    connection:\n      type: mysql\n      host: \u003cinstance-ip-address\u003e\n      port: 3306\n      user: ${MYSQL_DB_USERNAME}\n      password: ${MYSQL_DB_PASSWORD}\n    databases:\n      - \u003cdatabase-name\u003e\n    advanced:\n      source:\n        database.ssl.mode: required\n```\n\nIf you don't set `database.ssl.mode` and the instance only accepts encrypted\nconnections, the pipeline deployment fails with an error like\n`Access denied for user '\u003cusername\u003e'@'\u003cip-address\u003e' (using password: YES)`. This\nerror looks like a credentials problem, but Cloud SQL is actually rejecting the\nunencrypted connection.\n\nThe `required` mode encrypts the connection but doesn't verify the server\ncertificate. To verify the certificate as well, set the source's `CACERT` secret\nto the instance's server CA certificate and choose a verifying mode, as described in\n[Connect over TLS or mTLS](https://redis.io/docs/latest/integrate/redis-data-integration/data-pipelines/prepare-dbs/my-sql-mariadb#7-connect-over-tls-or-mtls).\n\n## Failover on Regional instances\n\nA Regional (high availability) Cloud SQL instance has a standby in a second\nzone. During a failover, Cloud SQL promotes the standby to primary and keeps the\nsame IP address. Expect the following behavior when this happens:\n\n- Clients, including your application, can't connect to the instance for up to\n  about a minute while the failover runs. Use connection retry logic in your\n  application to handle this.\n- RDI doesn't need a restart or any manual step. The RDI collector detects that\n  its binlog connection is no longer working, reconnects to the new primary, and\n  then captures the changes that were committed while it was disconnected.\n- Expect about one minute of extra change data capture (CDC) lag after the\n  instance becomes available again, while the collector detects the lost\n  connection and catches up.\n",
  "tags": ["docs","integrate","rs","rdi"],
  "last_updated": "2026-10-30T16:31:14Z"
}
