# MySQL

> Source: https://docs.clonepartner.com/connectors/mysql/

<!-- sources: src/connectors/mysql.ts, src/connectors/readonly-sql.ts, src/connectors/readonly-pool.ts, references/envoy/connectors.md -->

# MySQL

The `mysql` connector queries and writes MySQL tables over a connection pool, with a separate read-only pool for dashboard queries.

## When to use it

Use `mysql` as a relational source or destination, and as a mapping database or cursor store for sync tasks. For PostgreSQL use [PostgreSQL](/connectors/postgres/); for SQL Server use [MS SQL Server](/connectors/mssql/).

## Configuration

| Key | Type | Required | Default | Description |
|---|---|---|---|---|
| `connection_string` | string | Yes | — | MySQL connection string (`mysql://user:pass@host:3306/db`), stored as a secret |
| `max_connections` | number | No | 10 | Max pool connections |
| `idle_timeout` | number | No | 30 | Idle connection timeout in seconds |
| `ssl` | string | No | — | SSL mode: `disable`, `prefer`, `require` |
| `readonly_connection_string` | string | No | — | Optional read-only connection string for dashboard queries (separate pool). Defaults to the primary with `SESSION TRANSACTION READ ONLY`. Stored as a secret. |
| `readonly_max_connections` | number | No | 2 | Max connections on the read-only pool |

## Methods

| Method | Arguments | Returns | Behavior |
|---|---|---|---|
| `find` | `table` (required), `filter`, `select`, `limit`, `offset`, `order_by` | array | Streams matching rows to downstream steps |
| `find_one` | `table` (required), `filter`, `select` | object | Returns the first matching row |
| `insert_one` | `table` (required), `data` (required) | object | Inserts a single record |
| `upsert` | `table` (required), `data` (required), `conflict_columns` (required), `update_columns` | object | `INSERT ... ON DUPLICATE KEY UPDATE`; updates `update_columns` (or all non-conflict columns) |
| `delete` | `table` (required), `filter` | object | Deletes rows matching the filter |
| `execute` | `statements` (required) | object | Executes a raw SQL statement on the primary pool |
| `select` | `sql` (required), `params` | array | Runs a read-only `SELECT` on the dedicated read pool (`SELECT` or `WITH` only) |

`filter` uses the shared JSON filter syntax (`gt`, `gte`, `lt`, `lte`, `ne`, `in`, `nin`, `like`, `ilike`, `regex`, `exists`, plus `and`/`or`). `ilike` compiles to `LOWER(col) LIKE LOWER(pattern)` and `regex` to the `REGEXP` operator.

## Example

```yaml
name: export_recent_orders
connectors:
  source:
    type: mysql
steps:
  - name: read_orders
    type: call_method
    config: |
      {
        "connector": "source",
        "method": "find",
        "args": { "table": "orders", "filter": { "created_at": { "gt": "2026-01-01" } } }
      }
```

The matching `connectors.yaml` entry for CLI runs:

```yaml
source:
  type: mysql
  config:
    connection_string: ${MYSQL_CONNECTION_STRING}
```

## Behavior notes

- `select` rejects anything that is not a `SELECT` or `WITH ... SELECT` statement and runs on a separate pool whose sessions are set to read-only transactions. Point `readonly_connection_string` at a replica to isolate dashboard load.
- The connector implements the mapping-DB interface (a `resource_mapping` table created on first use) and the cursor store (`envoy_cursors`), so it can serve as `lookup_connector` or `cursor_store` for sync tasks. See [Idempotent sync and the mapping DB](/building/idempotent-sync/).
- Upserts rely on a unique key covering `conflict_columns` — MySQL's `ON DUPLICATE KEY UPDATE` fires only when a unique constraint matches.

## Related

- [Connectors overview](/connectors/) — all compiled connector types
- [PostgreSQL](/connectors/postgres/) — the same method set for PostgreSQL
- [Idempotent sync and the mapping DB](/building/idempotent-sync/) — how the mapping table is used
