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, TiDB, and Databend.
Quick setup
1
Create Connection
Click New Connection… on the welcome window and pick MySQL
2
Test and Save
Fill in host, port, and credentials, click Test Connection, then Save & Connect
Connection settings
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
Common setups
Users & Roles
Database > Users & Roles manages users, roles, and privileges. Changes are staged and shown as SQL before they run. See 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.


EXPLAIN rendered as a visual plan
Browsing
The sidebar lists every accessible database with each table’s structure and DDL. Switch databases withCmd+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 againstmax_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.
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:
ALTER TABLE each. This query writes them for the current database; run the statements it returns:
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.Limitations
- No Unix socket connections. Give the connection a host and a port, and leave networking on in the server.
LOAD DATA LOCAL INFILEis 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;.
