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

# MySQL

> Let agents inspect tables, run read-only SQL, read query plans and see what is slow or waiting on locks in your MySQL database

The MySQL connector works with any server that speaks the MySQL protocol: self-hosted MySQL 5.7 and 8.x, Amazon RDS and Aurora MySQL, Google Cloud SQL, Azure Database for MySQL, PlanetScale, MariaDB and TiDB. JSON, spatial and binary columns come back as text or base64.

## Tools

| Tool                         | What it returns                                                                                                                                                                                   |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Test Connection**          | Server version, user, default database, whether TLS is on, the user's grants, and warnings about administrative or write privileges. Errors say whether authentication, the network or TLS failed |
| **List Schemas**             | Databases with their character set and number of tables                                                                                                                                           |
| **List Tables**              | Tables and views with engine, estimated row count and data plus index size                                                                                                                        |
| **Describe Table**           | Columns (type, nullability, default, key, comment), indexes with their columns, foreign keys, engine, row estimate and size                                                                       |
| **Run Query**                | Rows of one read-only `SELECT`, as objects, with `truncated` when more existed                                                                                                                    |
| **Explain Query**            | `EXPLAIN FORMAT=JSON` plus a summary (cost, access type, chosen index); `analyze: true` runs `EXPLAIN ANALYZE` for real timings                                                                   |
| **Active Queries and Locks** | Every non-sleeping session: query, state, runtime and blocking sessions, open InnoDB transactions (including idle ones) and waiting row locks                                                     |
| **Slow Queries**             | Top statement shapes from `performance_schema` by mean time, total time, calls or rows examined                                                                                                   |
| **Table Stats**              | Size, free space and auto-increment per table, plus reads, writes and full-scan rows when `performance_schema` is readable                                                                        |
| **Execute Statement**        | Runs one write statement and commits it. Needs a `read_write` connection and a confirmation on every call                                                                                         |

## Safety

* **Read-only by default, enforced by MySQL.** Every read tool runs inside `START TRANSACTION READ ONLY`, so the server refuses a write even from a stored function the query calls. Run Query also refuses before sending anything: comments (`--`, `#`, `/* */`), backslashes, a second statement, and write keywords such as `INSERT`, `UPDATE` or `SELECT ... INTO OUTFILE`.
* **Limits on every call.** `max_execution_time` defaults to 15 s (up to 55 s with `timeout_seconds`; `max_statement_time` on MariaDB). Results stop at 500 rows (up to 5,000 with `max_rows`) and 1 MB, and Danube stops reading from the server at the cap. A cut result has `truncated: true`.
* **Writes are a separate tool.** Execute Statement only runs on a connection stored with mode `read_write`, and every call returns a `confirm_token` first that the agent must show you and send back. Lock waits are limited to the call's timeout, so a DDL statement that cannot get its lock fails instead of queueing every other query behind it.
* **No secrets in results.** Passwords, connection strings and keys are removed from every error message and masked in results. `LOAD DATA LOCAL` is off.
* **Every call is audited.** The audit log records who called, which tool, a SHA-256 of the SQL (never the text), the row count, the duration and the outcome.

## Create a read-only user

Connect with a user that can only read. Test Connection warns when the user holds administrative or write privileges.

```sql theme={null}
CREATE USER 'danube_readonly'@'%' IDENTIFIED BY 'choose-a-long-password'
  WITH MAX_USER_CONNECTIONS 5;
GRANT SELECT, SHOW VIEW ON app.* TO 'danube_readonly'@'%';
-- Lets Active Queries see other sessions (a global privilege)
GRANT PROCESS ON *.* TO 'danube_readonly'@'%';
-- Slow Queries, lock waits and Table Stats read performance_schema
GRANT SELECT ON performance_schema.* TO 'danube_readonly'@'%';
```

Repeat the `GRANT SELECT, SHOW VIEW` line for every database agents should see. Add `REQUIRE SSL` to the `CREATE USER` to refuse unencrypted logins. `performance_schema` is on by default in MySQL 8; on RDS and Aurora it is the `performance_schema` parameter (a reboot applies it). Without it, Slow Queries answers `available: false` with these steps and Table Stats leaves out the activity counters.

## Connect

Open **MySQL** in the dashboard's tool catalog and click **Connect**, or let the agent call `store_credential`. Fill in host, port, database, user, password and SSL mode. Mode stays **Read only** unless you want Execute Statement to work.

SSL modes: `required` encrypts without checking the certificate (the default for public hosts), `verify_identity` also checks the certificate and host name against the system CAs or the CA certificate you paste (RDS and Cloud SQL publish theirs), `preferred` uses TLS when the server offers it, `disabled` never does. Storing a CA certificate upgrades `required` to `verify_identity`.

How Danube reaches the database depends on where it lives:

<Tabs>
  <Tab title="Public endpoint">
    Managed databases with a public endpoint (RDS or Aurora with public access, Cloud SQL with a public IP, PlanetScale, Azure) connect directly. TLS is required by default. Allow Danube's egress addresses in the database's firewall or security group: see [Connect your production database safely](/connectors/production-database#allowlist-danubes-addresses).
  </Tab>

  <Tab title="Private network, SSH bastion">
    Fill in the **SSH bastion** fields: the bastion's public host, user, private key and host key fingerprint. Set **Host** to the database's private address as the bastion sees it. Danube verifies the bastion's host key against the fingerprint you stored and never trusts a new key on first use. Leave the fingerprint empty once and Test Connection prints the key the bastion presented, so you can check it and paste it in.
  </Tab>

  <Tab title="Private network, data-plane agent">
    Run the [data-plane agent](/organizations/data-plane) inside the network and store the password as a reference, for example `env://MYSQL_PASSWORD`. The call then runs on the agent, which resolves the reference locally. Nothing inbound is opened, and the password never reaches Danube. Build the agent image with `DANUBE_DB_ENGINES=mysql`.
  </Tab>
</Tabs>

Run **Test Connection** after saving. It tells you which of these failed: the credentials (`auth_required`), the network (`connection_error`, `destination_blocked`) or TLS (`tls_error`).

## Example prompts

* "Which tables in the `app` database are biggest, and how many rows do they have?"
* "Find orders from the last hour with `status = 'payment_failed'` and group them by customer."
* "Why is this query slow? Explain it and suggest an index."
* "Is anything waiting on a lock right now, and which session holds it?"
* "What are the ten statements that examine the most rows?"
