Automating MySQL Slow Query Triage with an AI Database Agent
A query regression landed in Tuesday's deploy. Checkout latency crept from 180 ms to 900 ms at p95, a few customers complained, someone bumped the RDS instance size, and the ticket that said "check the slow log" sat in the backlog for two weeks — because nobody on the team is a DBA, and reading a MySQL slow query log is nobody's favorite Thursday.
That timeline is the real cost of slow queries at most mid-market companies. Not the diagnosis — part one of this series showed the five patterns behind almost every slow query, and part two walked through finding them with the slow log, performance_schema, and EXPLAIN ANALYZE. The diagnosis is teachable. The cost is the gap: the days or weeks between a regression shipping and a human sitting down with the evidence.
This is part three, and it covers closing that gap: how Tony, CloudThinker's database agent, watches your MySQL slow-query surface continuously, brings you index recommendations with the evidence attached, and — the part your security review will ask about first — what it refuses to do without your explicit approval.
How Tony connects: a read-only user, about 5 minutes
Tony connects to MySQL the way you'd want any third party to: with a dedicated database user that can read metadata and performance data, and nothing else. No plugin in the server, no binlog tap, no write privileges at connection time. You create the user, paste the endpoint and credentials into CloudThinker, and the first analysis starts. The MySQL connection guide has the exact statements; the shape is:
CREATE USER 'cloudthinker'@'%' IDENTIFIED BY '<strong-password>';
GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'cloudthinker'@'%';
SELECT covers performance_schema, the sys schema, and information_schema; PROCESS lets Tony see the live processlist and run EXPLAIN on queries it didn't issue; REPLICATION CLIENT covers replication lag checks. Your security team can read that grant in one line and see exactly what is — and isn't — possible.
The whole flow takes about five minutes against RDS, Aurora MySQL, Cloud SQL, or self-hosted MySQL 8.x.
What Tony watches continuously
Everything in part two, on a loop instead of an afternoon:
- Statement digests in
performance_schema. Tony readsevents_statements_summary_by_digeston a rolling basis, so it ranks queries by total time — count × latency — not just the single worst offender. The 3 ms query running 500,000 times a day shows up next to the 40-second report. - The slow query log, properly configured. If your
long_query_timeis still the 10-second default, Tony's first finding is usually that your slow log is effectively off — everything between "annoying" and "catastrophic" is invisible. It will propose a sane threshold before it proposes anything else. - Execution plans and their regressions. Full table scans, filesorts, temporary tables spilling to disk, index-defeating implicit casts — the patterns from part one, detected from digest statistics and confirmed with
EXPLAIN. - Baselines per query digest. This is the part a point-in-time audit can't do. Tony knows what each digest's latency looked like last week, so Tuesday's deploy regressing one endpoint's query is a finding on Tuesday — with the before/after plans side by side — not a mystery two weeks later.
- The supporting cast: lock waits and contention hot spots, unused and redundant indexes, buffer pool pressure, replication lag.
Index recommendations come with evidence, not vibes
An index suggestion you can't verify is a liability — every index you add taxes every write and competes for buffer pool. So each recommendation Tony makes carries its case file:
- the query digest and its call sites (count, total time, rows examined vs. rows returned);
- the current
EXPLAINoutput showing the scan or filesort; - the proposed index definition and why those columns in that order;
- the projected plan after the index, checked with
EXPLAIN ANALYZE-style measurement where a safe replica or staging copy is available; - the write-amplification cost: how many inserts/updates per day will now maintain this index.
For drops it's the same standard in reverse: an index is flagged unused only after sys.schema_unused_indexes and digest history agree over a meaningful window, and Tony will suggest making it invisible first — a reversible experiment — before ever suggesting removal.
Graduated autonomy: no DDL without a human
Every action class has an autonomy level you set per database:
- Notify — Tony reports the finding with evidence. The default for everything.
- Suggest — Tony proposes the specific change (index DDL, config value, query rewrite) with projected impact and a rollback path.
- Approve — Tony prepares the exact statement and executes only after a named human approves it in the app.
- Autonomous — Tony executes and reports. Teams that use this at all reserve it for reversible, low-blast-radius actions on non-production databases — and usually only after weeks of watching Tony be right at the Approve level.
Two lines worth underlining. First, schema changes are never autonomous by default — CREATE INDEX, ALTER TABLE, DROP INDEX sit behind approval unless you deliberately decide otherwise, and executing them at all requires you to grant a separate scoped write credential; the read-only connection user physically cannot run DDL. Second, everything lands in an audit trail: finding, evidence, proposal, approver, statement executed, timestamp. When someone asks "who added that index and why," the answer is one link.
What a first analysis typically finds
Illustrative numbers — a composite of first scans on mid-market SaaS databases in the 100–500 GB range. Yours will differ.
| Finding | Evidence | Typical impact |
|---|---|---|
| Missing composite index | orders lookup on (customer_id, status) examines 4.2M rows to return ~40 |
p95 620 ms → single-digit ms |
| Implicit cast defeating an index | WHERE external_id = 12345 against a VARCHAR column forces a full scan |
~90 s of scan time per hour |
| Filesort spilling to disk | Reporting query sorts on an unindexed column; on-disk temp tables ~1,100×/day | I/O contention during business hours |
| N+1 digest | Same 3 ms lookup executed ~480K times/day from one endpoint | ~24 min of DB time daily |
| Redundant indexes | 9 indexes fully covered by a wider prefix | Slower writes, wasted buffer pool |
| Hot-row lock contention | Counter-table updates averaging 180 ms lock wait at peak | Latency spikes that look random |
| Slow log misconfigured | long_query_time at the 10 s default |
The whole 200 ms–10 s band invisible |
The shape repeats across environments: one or two missing/misused indexes explain most of the user-facing p95, one chatty endpoint dominates total load, and the slow log wasn't actually catching any of it. None of these findings is exotic — every one is detectable with part two's playbook. The value is that this table refreshes continuously, and each row arrives with an approval-gated fix attached instead of a ticket that waits two weeks.
Prompts to try in your first session
Tony is conversational — you ask in plain language and get answers that cite performance_schema evidence you can verify yourself:
"@tony what are our top 10 queries by total execution time this week, and which ones regressed after Tuesday's deploy?"
"@tony why is the order search doing a full table scan? Propose an index and show me the before and after plans."
"@tony which indexes haven't been used in 30 days? Show the evidence, and stage the drops as invisible-index changes for my approval."
Because every answer links back to the underlying digests and plans, the workflow is verify-then-approve, not trust-and-hope.
What Tony will not do
- Write to your database from the connection credential. The default user is read-only; remediation requires a separately granted, scoped credential.
- Run DDL without approval. No index creation, no drops, no
ALTER TABLE, unless a human approved that statement or you explicitly set that action class to Autonomous for that database. - Kill queries or change server config silently. Same approval gates, same audit trail.
- Make schema-design decisions for you. Tony will show you that the counters table is a contention hot spot; whether to shard it, queue it, or move it to Redis is an engineering call, and it stays yours.
From two-week backlog to same-day finding
You know why MySQL queries go slow, and you know how to triage them with native tools. What a team without a full-time DBA can't sustain is the cadence — reading digests weekly, re-checking plans after every deploy, keeping the slow log honest. That's not an effort problem; it's an automation problem. Teams that move from reactive slow-log archaeology to continuous, approval-gated query management typically cut their worst p95 endpoints by 50–90% in the first month, mostly from a handful of well-evidenced indexes.
Try CloudThinker free — 100 premium credits, no card required — connect MySQL with the read-only guide, and see your own first findings table before the next deploy ships a regression.
