Description:
When calling connection.abort while the connection is executing a query, the connection will not abort until the query is completed (which makes the abort meaningless).
This only happens when we use multiple hosts (MultiHostConnectionProxy) because the invoke method is synchronized.
How to repeat:
Run this java code (with database in localhost:3306/db and user:password:
import java.sql.*;
import java.util.concurrent.*;
public class MySqlDeadlock {
public static void main(String[] args) throws Exception {
Executor executor = Executors.newFixedThreadPool(5);
try (Connection connection = DriverManager.getConnection(
"jdbc:mysql://address=(protocol=tcp)(host=localhost)(port=3306),address=(protocol=tcp)(host=localhost)(port=3306)/db",
"user", "password"); Statement statment = connection.createStatement()) {
System.out.println("Going to MySQL");
executor.execute(() -> {
try {
Thread.sleep(1000l);
System.out.println("Killing...");
connection.abort(executor);
System.out.println("Killed");
} catch (Exception e) {
e.printStackTrace();
}
});
statment.executeQuery("SELECT SLEEP(5)");
System.out.println("I'm back");
}
}
}
Suggested fix:
Make the locking smarter.