> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zwiron.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL Connector

> Sync MySQL with binlog CDC, incremental, or full refresh to Snowflake, BigQuery, and warehouses via Zwiron.

<Info>
  **Live — enterprise connector.** Fully supported today (SAT-validated). One of Zwiron's five production connectors: PostgreSQL, MySQL, MongoDB, Snowflake, BigQuery.
</Info>

Zwiron supports MySQL 5.7+ and MySQL 8.x as both a source and destination, with full CDC support via the binary log (binlog).

***

## Supported sync modes

| As source | Full Refresh | Incremental | CDC |
| --------- | ------------ | ----------- | --- |
|           | ✅            | ✅           | ✅   |

| As destination | Write modes             |
| -------------- | ----------------------- |
|                | Append, Upsert, Replace |

***

## Connection details

| Field    | Description                                                                                                  |
| -------- | ------------------------------------------------------------------------------------------------------------ |
| Host     | Hostname or IP of your MySQL server                                                                          |
| Port     | Default: `3306`                                                                                              |
| Database | The database name                                                                                            |
| Username | MySQL user for Zwiron                                                                                        |
| Password | User's password                                                                                              |
| TLS      | Default: `skip-verify` (encrypts; use for Cloud SQL / managed MySQL). Set `true` if you trust the server CA. |

***

## Connection string

You can paste a URI into the connection form to autofill fields:

```text theme={null}
mysql://USER:PASSWORD@HOST:3306/DATABASE
```

Optional TLS query param:

```text theme={null}
mysql://USER:PASSWORD@HOST:3306/DATABASE?tls=skip-verify
```

### Passwords with special characters

If the password contains URI-reserved characters, **percent-encode** them in the connection string. Otherwise the URI is parsed wrong (host/user look broken) and auth fails.

| Character in password | Encode as |
| --------------------- | --------- |
| `@`                   | `%40`     |
| `:`                   | `%3A`     |
| `/`                   | `%2F`     |
| `?`                   | `%3F`     |
| `#`                   | `%23`     |
| `%`                   | `%25`     |
| `[`                   | `%5B`     |
| `]`                   | `%5D`     |
| `\`                   | `%5C`     |
| `,`                   | `%2C`     |
| ` ` (space)           | `%20`     |

**Example**

Password: `4@p%,]PplAa@,P\%`

Encoded password: `4%40p%25%2C%5DPplAa%40%2CP%5C%25`

```text theme={null}
mysql://mysql-ziron:4%40p%25%2C%5DPplAa%40%2CP%5C%25@136.116.160.184:3306/test?tls=skip-verify
```

<Tip>
  Prefer filling **User** and **Password** as separate fields when the password is complex — Zwiron stores them correctly without manual encoding. Use encoding only when pasting a full URI.
</Tip>

***

## Permissions

### For a source (read-only)

```sql theme={null}
CREATE USER 'zwiron'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT ON your_database.* TO 'zwiron'@'%';
FLUSH PRIVILEGES;
```

### For a destination (read-write)

```sql theme={null}
CREATE USER 'zwiron'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON your_database.* TO 'zwiron'@'%';
FLUSH PRIVILEGES;
```

### For CDC (additional permissions)

```sql theme={null}
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'zwiron'@'%';
FLUSH PRIVILEGES;
```

***

## Enabling CDC

### Step 1 — Enable binary logging

Add to `/etc/mysql/my.cnf` (or `my.ini` on Windows):

```ini theme={null}
[mysqld]
server-id           = 1
log_bin             = /var/log/mysql/mysql-bin.log
binlog_format       = ROW
binlog_row_image    = FULL
expire_logs_days    = 7
```

Restart MySQL after making this change.

### Step 2 — Verify binary logging is enabled

```sql theme={null}
SHOW VARIABLES LIKE 'log_bin';       -- should be ON
SHOW VARIABLES LIKE 'binlog_format'; -- should be ROW
```

### Step 3 — Enable CDC in Zwiron

When creating a pipeline, select **CDC** as the sync mode. Zwiron will connect using the binlog position automatically.

***

## Notes for managed MySQL

### Amazon RDS for MySQL

Binary logging is enabled by default. Ensure the parameter group has:

* `binlog_format = ROW`
* `binlog_row_image = FULL`

Grant replication permissions:

```sql theme={null}
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'zwiron'@'%';
```

### Amazon Aurora MySQL

Same as RDS MySQL. Binary logging must be enabled in the cluster parameter group.

### Google Cloud SQL for MySQL

Enable binary logging in the Cloud SQL instance settings (Backups → Enable binary logging). Replication user setup is the same.

#### Hosted mode checklist (Cloud SQL)

Customers connecting Cloud SQL to **Zwiron Hosted** should do all of the following — this is the supported path, not a workaround:

1. **Public IP** enabled (Private IP alone is not reachable from Zwiron Hosted)
2. **Authorized Networks** — add **every** [Zwiron egress IP](/concepts/network-access) as `/32` (CIDR). Do not use **Use My IP**
3. **Database user** — Cloud SQL → **Users** → **Add User Account**:
   * Built-in authentication
   * **Allow any host (%)**
   * Dedicated user (not only `root`)
4. **Grants on the database** — creating a Cloud SQL user does not always grant table access. As an admin:

```sql theme={null}
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP
  ON `test`.* TO 'mysql-ziron'@'%';
FLUSH PRIVILEGES;
```

5. **Database** exists under Cloud SQL → Databases
6. In Zwiron, leave **TLS** at the default (`skip-verify`)
7. **Profile after sync finishes** — mid-sync, data may sit in `*_zw_stg` staging tables; catalog fills once final tables exist and you re-run Profile

**Security model:** lock down who can reach the instance with Authorized Networks (Zwiron IPs only). Use `%` on the MySQL user so HA egress works; least-privilege grants on the database. For no public IP at all, use [Agent mode](/concepts/execution-modes).

If Test Connection fails with *"The request did not reach the server,"* Authorized Networks is almost always the cause.\
If it fails with *"Access denied,"* the user was not created in Cloud SQL Users, or the password is wrong.\
If Profile shows **0 tables**, grant access on the database, wait for any running job to complete, then Profile again.

***

## MySQL 8.4 and MySQL 9.x

MySQL 8.4 deprecated `SHOW MASTER STATUS` in favour of `SHOW BINARY LOG STATUS`, and MySQL 9.x removed it entirely. Zwiron detects your MySQL version automatically and uses the correct command — no configuration needed.

***

## Related guides

* [MySQL CDC to BigQuery](/guides/mysql-cdc-to-bigquery)
* [Hosted vs agent](/guides/hosted-vs-agent)
* Product page: [MySQL → BigQuery](https://zwiron.com/integrations/mysql-bigquery)

## Troubleshooting

<AccordionGroup>
  <Accordion title="Binary logging is not enabled">
    You'll see the error **"MySQL binary logging is not enabled on this server. CDC requires binlog to be active."** if the MySQL server was started without binlog enabled.

    Add the following to your MySQL config file (`/etc/mysql/my.cnf` or `my.ini` on Windows) and restart the server:

    ```ini theme={null}
    [mysqld]
    server-id        = 1
    log_bin          = /var/log/mysql/mysql-bin.log
    binlog_format    = ROW
    binlog_row_image = FULL
    ```

    Verify it is active after restarting:

    ```sql theme={null}
    SHOW VARIABLES LIKE 'log_bin';       -- must be ON
    SHOW VARIABLES LIKE 'binlog_format'; -- must be ROW
    ```

    For managed databases (RDS, Cloud SQL, Azure), enable binary logging through the cloud console rather than editing config files directly — see the **Notes for managed MySQL** section above.
  </Accordion>

  <Accordion title="Access denied for REPLICATION SLAVE">
    Ensure the Zwiron user has been granted `REPLICATION SLAVE` and `REPLICATION CLIENT` at the global level (`ON *.*`), not just on a specific database.
  </Accordion>

  <Accordion title="Binary log position is invalid">
    This can happen if the binlog files have been rotated and the saved position no longer exists. The job will perform a full re-sync automatically.
  </Accordion>

  <Accordion title="Tables without primary keys are skipped in CDC">
    MySQL CDC requires tables to have a primary key. Tables without a primary key will be synced using Full Refresh mode instead.
  </Accordion>

  <Accordion title="Clear text authentication / caching_sha2_password">
    MySQL 8 defaults to `caching_sha2_password`. Over TLS, the password is sent inside the encrypted session; Zwiron handles that automatically.

    If you still see cleartext or auth errors on Cloud SQL:

    1. Leave **TLS** at `skip-verify` (default for MySQL in Zwiron).
    2. Confirm [Authorized Networks](/concepts/network-access) include all Zwiron egress IPs.
    3. Create the user in **Cloud SQL → Users** (Built-in, Allow any host `%`) — do not assume a SQL-only user exists.
    4. Reset the password in the console and paste it exactly into Zwiron.
  </Accordion>

  <Accordion title="Access denied for user (Error 1045)">
    The username or password is wrong, or the user was never created in the cloud console. Open **Cloud SQL → Users**, add a built-in user with **Allow any host (%)**, then retry.
  </Accordion>
</AccordionGroup>
