MySQL Runaway Queries and KILL
KILL QUERY stops the statement and leaves the connection alive; KILL drops the whole connection and rolls back its transaction. The victim sees ERROR 1317 and the difference between the two matters more than it sounds.
Troubleshooting Guide 37 of 45 Intermediate
- OSUbuntu 26.04 LTS
- MySQL8.4.10-0ubuntu0.26.04.1
- Topologydb-a01 source, db-b01 and db-c01 replicas
- TimeAbout 13 min
A killed statement rolls back, and rolling back a large transaction can take longer than the statement did. Killing is not always the fast option.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| db-a01 | 192.168.0.81 | Ubuntu 26.04 LTS | Primary / Source / Replica Set Member 1 | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when a query is consuming the server and has to stop. This matters because KILL QUERY ends the statement and leaves the connection alive while KILL drops the connection - and inside an open transaction those have very different consequences.
- starting something expensive, finding it, and stopping it with
KILL QUERY - using
KILLwithout QUERY against a target inside an open transaction, and watching the difference - confirming the row the killed transaction had updated is intact
Before you start
- The 400,000-row
eventstable from the performance track.
-
Start something expensive, find it, and stop it
A self-join of a 400,000-row table on a column with ten distinct values - each row matches roughly forty thousand others, so this is billions of comparisons. A realistic accident: a missing join condition or a forgotten filter.
The process list is searched by the statement's own text rather than by a guessed id, which is how you find the right connection when there are dozens.
INFOholds the running statement, soLIKEon it is a reliable way to identify a specific query.KILL QUERYstops the statement. The victim seesERROR 1317: Query execution was interrupted- an unmistakable message, distinct from a timeout or a syntax error, so a well-behaved application can log it as "cancelled" rather than "failed".The connection survives.
KILLwithoutQUERYwould have closed it entirely and rolled back any open transaction - which is what you want for a leaked connection and not what you want for an application mid-request.bash Example session sudo bash -c 'mysql appdb -e "SELECT COUNT(*) FROM events e1 JOIN events e2 ON e1.customer_id = e2.customer_id" >/tmp/runaway.out 2>&1 & sleep 3; ID=$(mysql -N -e "SELECT ID FROM information_schema.PROCESSLIST WHERE INFO LIKE \"%e1 JOIN events e2%\" LIMIT 1"); echo "runaway connection id: $ID"; mysql -e "KILL QUERY $ID"; sleep 1; cat /tmp/runaway.out; wait'runaway connection id: 97ERROR 1317 (70100) at line 1: Query execution was interruptedExpected resultThe connection id, then
ERROR 1317 (70100): Query execution was interrupted.Success conditionYou can stop one statement without dropping the connection running it.
-
Now use KILL without QUERY, and watch the difference
The same setup, but the target is inside an open transaction that has already updated a row - and this time the statement is bare
KILL.The victim sees
ERROR 2013: Lost connection to MySQL server during query, not 1317. That is a different failure entirely: 1317 says *your query was cancelled and you are still connected*; 2013 says *the connection is gone*. An application distinguishing them will retry one and reconnect for the other.The count afterwards is 0 - the connection is no longer in the process list. And because the connection closed with a transaction open, that transaction was rolled back: nothing it had done survives.
So the choice is about scope.
KILL QUERYfor a runaway statement on a connection you want to keep.KILLfor a leaked or hostile connection, accepting that its open work is discarded.bash Example session sudo bash -c 'mysql appdb -e "START TRANSACTION; UPDATE customers SET credit=credit+1 WHERE id=1; SELECT SLEEP(20);" >/tmp/k1.out 2>&1 & sleep 3; ID=$(mysql -N -e "SELECT ID FROM information_schema.PROCESSLIST WHERE INFO LIKE \"%SLEEP(20)%\" LIMIT 1"); echo "target id: $ID"; mysql -e "KILL $ID"; sleep 1; echo "--- victim saw ---"; cat /tmp/k1.out; echo "--- still connected? ---"; mysql -N -e "SELECT COUNT(*) FROM information_schema.PROCESSLIST WHERE ID = $ID"; wait'target id: 12--- victim saw ---ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query--- still connected? ---0Expected result
ERROR 2013 (HY000): Lost connection to MySQL server during query, and a process-list count of 0 for that id.Success conditionYou can choose between cancelling a statement and closing a connection.
-
Confirm the row is intact
The row the killed transaction had updated, read back afterwards.
It holds a single consistent value. The killed transaction never committed, so InnoDB rolled its change back - the same mechanism the schema track demonstrated with an explicit
ROLLBACK, applied here because the connection died rather than because anyone asked.This is the guarantee that makes killing a connection a safe operation on a transactional engine. On a non-transactional one it would leave the row half-updated.
bash Example session sudo mysql --table appdb -e "SELECT id, credit FROM customers WHERE id = 1"+----+--------+| id | credit |+----+--------+| 1 | 126.50 |+----+--------+Expected resultOne row with a single consistent credit value.
Success conditionYou know a killed connection cannot leave a half-finished transaction.
Troubleshooting
KILLreturns immediately but the query keeps running.Why: The thread only notices the kill at certain points, and rollback takes time.
Fix:Watch
STATEin the process list.Rolling backmeans it is working - killing again does not help.Killing a long transaction made things worse.
Why: The rollback has to undo everything it did, holding locks the whole time.
Fix:For a long-running write, letting it finish is sometimes faster. Check
Innodb_rows_deletedor the rollback state before deciding.You killed the wrong connection.
Why: The id was read from a stale process list.
Fix:Match on
INFOrather than remembering an id. Ids are reused.ERROR 1095: You are not owner of thread.Why: Killing another account's connection needs
CONNECTION_ADMIN.Fix:Use an administrative account. Do not grant it to applications.