> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-fix-mysql-session-replay.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL

> Connect to MySQL 5.7 and later with the bundled MariaDB Connector/C driver

MySQL 8 accounts on `caching_sha2_password` connect on the first try, with no auth plugin to switch over. The same bundled driver covers 5.7 and later, plus [MariaDB](/databases/mariadb), [TiDB](/databases/tidb), and [Databend](/databases/databend).

## Quick setup

<Steps>
  <Step title="Create Connection">
    Click **New Connection…** on the welcome window and pick **MySQL**
  </Step>

  <Step title="Test and Save">
    Fill in host, port, and credentials, click **Test Connection**, then **Save & Connect**
  </Step>
</Steps>

## Connection settings

| Field        | Default     | Notes                                             |
| ------------ | ----------- | ------------------------------------------------- |
| **Host**     | `localhost` | TCP only, never a Unix socket                     |
| **Port**     | `3306`      |                                                   |
| **Username** | empty       | An empty field connects as your macOS login name  |
| **Password** | empty       | Stored in the macOS Keychain                      |
| **Database** | empty       | Optional. Leave it empty to browse every database |

Every connection sets its session character set to `utf8mb4` once it logs in, over any `init_connect` the server runs, so emoji and non-Latin text round-trip untouched. A connect attempt gives up after 10 seconds.

## Connection URL

```text theme={null}
mysql://user:password@host:3306/database
```

Opening a URL connects directly. See [Connection URL Reference](/connections/urls).

## Common setups

| Where             | Settings                                                                                                               |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Homebrew          | `localhost:3306`                                                                                                       |
| Docker            | `localhost` with the mapped port, password from `MYSQL_ROOT_PASSWORD`                                                  |
| MAMP Pro          | `localhost:8889`, user and password `root`                                                                             |
| AWS RDS / Aurora  | Endpoint hostname, password or [AWS IAM](/connections/aws-iam), which signs a fresh 15-minute token on each connect    |
| Google Cloud SQL  | **Connect via > Cloud SQL Auth Proxy** and the instance name. See [Cloud SQL Auth Proxy](/connections/cloud-sql-proxy) |
| Remote production | [SSH tunnel](/connections/ssh-tunneling)                                                                               |

## Users & Roles

**Database > Users & Roles** manages users, roles, and privileges. Changes are staged and shown as SQL before they run. See [Users & Roles](/features/users-roles).

## Query plans

`EXPLAIN FORMAT=JSON`, `EXPLAIN FORMAT=TREE`, and `EXPLAIN ANALYZE` render as a plan diagram or tree; plain multi-column `EXPLAIN` stays in the results grid. See [EXPLAIN Visualization](/features/explain-visualization).

<Frame caption="EXPLAIN rendered as a visual plan">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-fix-mysql-session-replay/maVOdMwCk9sfuVvg/images/explain-diagram.png?fit=max&auto=format&n=maVOdMwCk9sfuVvg&q=85&s=318c43cfa4ee6d8c9382d8bf67f0ab60" alt="Visual EXPLAIN plan diagram" width="3026" height="1720" data-path="images/explain-diagram.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-fix-mysql-session-replay/maVOdMwCk9sfuVvg/images/explain-diagram-dark.png?fit=max&auto=format&n=maVOdMwCk9sfuVvg&q=85&s=cd0083a0de7b66894c5939acf19e651c" alt="Visual EXPLAIN plan diagram" width="3028" height="1722" data-path="images/explain-diagram-dark.png" />
</Frame>

## Browsing

The sidebar lists every accessible database with each table's structure and DDL. Switch databases with `Cmd+K`. A tab keeps the database it was opened on; MySQL switches database in place, so that tab runs on the same connection rather than a second one.

Table and column comments show in the UI: dimmed after a table's name in the sidebar, and in the grid header tooltip. Turn that off under **View Options**, the button beside the sidebar’s filter field.

## Releasing an idle connection

A connection holds a server thread and one slot against `max_connections` for as long as it is open, and MySQL's `wait_timeout` rarely reclaims it because the connection check counts as activity on the server. **Release the Server Connection After**, in **Options**, hands the connection back after that many minutes of no queries and takes a new one on the next query. `0`, the default, keeps it.

To stop the check itself, set **Check connections** to **Only when I use the connection** in Settings > General. That is the connection-wide setting; this one is per connection and closes the connection rather than quietening it.

Reconnecting costs a TCP connect, the TLS handshake and authentication: measured at 2ms against a server on the same machine and 800ms to 1.9s across the internet. That cost lands on the first query after an idle period, so leave this at `0` for a remote server unless the slot matters more than the wait.

A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, `FLUSH TABLES WITH READ LOCK`, an open `HANDLER`, a user variable, a changed session setting, a database selected with `USE`, or a stored routine call, whose body is opaque. The statements a dump runs inside `/*!40101 ... */` count, since the server executes them. The transaction comes from the server itself, so one opened by `SET autocommit = 0` or by an `XA START` counts as well.

## When the server drops the connection

A read that fails because the server closed the connection is run once more on a new one, and only from a session holding nothing: the same list as above. Every other statement reports the error, because the second session answers from different state. Measured on MySQL 8.4.11, replaying regardless: `SELECT @total` came back `NULL` where it had come back 42, and `SELECT DATABASE()` came back as the connection's own database rather than the one `USE` had selected, neither of them raising anything. `LAST_INSERT_ID()`, `ROW_COUNT()`, `FOUND_ROWS()` and `CONNECTION_ID()` are never replayed either, whatever the session holds: their answer belongs to the connection that is gone.

A connection with startup commands that run `SET` is holding a changed session setting from the moment it opens, so it reports the error rather than retrying. **Database > Reconnect** takes a new connection and puts back the database and the startup commands.

## Garbled non-Latin text

A comment or value that reads `ãƒ¡ãƒ¼ãƒ«` where `メール` belongs was written by a client that sent UTF-8 while telling the server it was sending Latin 1. A `mysql` command-line client without a UTF-8 locale does that, and so does a MySQL 5.7 container loading its `docker-entrypoint-initdb.d` scripts, and so does any client on a server whose `init_connect` runs `SET NAMES latin1`. The server stored the garbled form, so every UTF-8 client shows the same thing.

To work with such a database the way that client did, set **Encoding** to **UTF-8 via Latin 1** in **Options** and reconnect. Text written through Latin 1 then reads correctly, text stored correctly still reads correctly, and whatever you save is stored the way the old client stored it, so the application that wrote the data keeps reading it.

<Warning>
  With **UTF-8 via Latin 1**, a correctly stored value you edit is saved in the garbled form, and a table or column whose non-Latin name was stored correctly cannot be opened. Use it on a database written through Latin 1, never on one where applications write UTF-8.
</Warning>

An SQL export taken with **UTF-8 via Latin 1** holds the text as it reads, in UTF-8. Restoring it gives a database with the text fixed, which the old client then reads as `?`. Restore it where you are moving off that client, not as a backup of the database it still writes to.

To fix the stored text instead, convert it in place. The `WHERE` clause skips values that were stored correctly:

```sql theme={null}
UPDATE orders
SET note = CONVERT(CAST(CONVERT(note USING latin1) AS BINARY) USING utf8mb4)
WHERE note = CONVERT(CONVERT(note USING latin1) USING utf8mb4)
  AND CONVERT(CAST(CONVERT(note USING latin1) AS BINARY) USING utf8mb4) IS NOT NULL;
```

Table comments take one `ALTER TABLE` each. This query writes them for the current database; run the statements it returns:

```sql theme={null}
SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` COMMENT = ',
  QUOTE(CONVERT(CAST(CONVERT(TABLE_COMMENT USING latin1) AS BINARY) USING utf8mb4)), ';')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_COMMENT <> ''
  AND TABLE_COMMENT = CONVERT(CONVERT(TABLE_COMMENT USING latin1) USING utf8mb4)
  AND CONVERT(CAST(CONVERT(TABLE_COMMENT USING latin1) AS BINARY) USING utf8mb4) IS NOT NULL;
```

A column comment is part of the column's definition. Copy it from the **Structure** tab while **UTF-8 via Latin 1** is on, then switch back to **UTF-8**, reconnect, and paste it into the same column.

## SSL/TLS

New connections default to **Preferred**: TLS first, dropping to plain text only after an SSL handshake error. Pick **Verify CA** with the provider's certificate for strict validation. See [SSL/TLS](/connections/ssl).

## Limitations

* No Unix socket connections. Give the connection a host and a port, and leave networking on in the server.
* `LOAD DATA LOCAL INFILE` is refused by the driver. Load the file with **File > Import > Import Data…** instead.

## Troubleshooting

**Connection refused**: check the server is running (`brew services start mysql`), the port is right, and `skip-networking` is not set.

**Access denied for user '…'@'…' (using password: YES)**: the password is wrong, or the grant does not cover the host you are connecting from. Check both with `SHOW GRANTS FOR 'user'@'host';`.

**Auth plugin errors**: `caching_sha2_password` needs no configuration. For any other plugin error, read the account's plugin with `SELECT user, plugin FROM mysql.user;`.
