Skip to content

fix(plugin-mysql): make socket read timeout follow the query timeout#1925

Merged
datlechin merged 1 commit into
mainfrom
fix/1921-mysql-read-timeout
Jul 21, 2026
Merged

fix(plugin-mysql): make socket read timeout follow the query timeout#1925
datlechin merged 1 commit into
mainfrom
fix/1921-mysql-read-timeout

Conversation

@datlechin

Copy link
Copy Markdown
Member

Fixes #1921.

Problem

With Settings > General > Query timeout set to 600s, a MySQL/MariaDB query or stored procedure that runs longer than about a minute without returning a packet fails with [2026] TLS/SSL error: Operation timed out (60), while the statement keeps running on the server. That makes the result ambiguous and risks running a statement twice.

Root cause

MariaDBPluginConnection.attemptConnect hardcoded MYSQL_OPT_READ_TIMEOUT = 30, with no relation to the configured query timeout. MariaDB Connector/C applies that as a per-read (inter-packet) timeout, set once at connect, so a query that emits no packet for ~30s is aborted client-side. The server-side timeout (SET SESSION max_execution_time / max_statement_time) is derived from the setting but never touches the socket timeout, and does not apply to stored procedures at all.

The connector does not multiply the read timeout (the "3x" wording is Oracle's libmysqlclient, a different library), and mysql_options on a live handle has no effect, so the derived value must be set at connect.

Fix

  • Derive the socket read/write timeout from the configured query timeout plus a 30s grace, so a long query runs for the full time allowed. A "No limit" (0) query timeout maps to no read-timeout cap, matching how native clients like Sequel Ace and DataGrip behave.
  • The query timeout reaches the plugin through the existing additionalFields config seam, injected app-side at driver creation. No PluginKit ABI change, no version bump.
  • Extract the derivation into a pure, unit-tested helper.

Retry safety (related)

executeWithReconnect reconnects and re-runs on connection-lost errors. On a plaintext connection a read timeout surfaces as error 2013, which was in the retry set, so a dropped connection could silently re-run an insert, update, or stored procedure. The retry is now gated on the statement being read-only, so it can never re-run a statement that changes data, while metadata SELECTs keep their stale-connection recovery.

Tests

  • MySQLSocketTimeoutTests: 0 stays infinite, negative stays infinite, finite adds the grace, large values clamp without overflow.
  • MySQLStatementClassificationTests: SELECT/SHOW/DESCRIBE/DESC read-only; INSERT/UPDATE/DELETE/CALL/REPLACE/DROP not; leading comments treated conservatively.

Out of scope

The plugin's internal reconnect does not re-apply the server-side SET SESSION timeout, and a settings change does not reach live sessions ("Applied to new connections"). Both are pre-existing and tracked separately.

@datlechin
datlechin merged commit 51a5cef into main Jul 21, 2026
2 checks passed
@datlechin
datlechin deleted the fix/1921-mysql-read-timeout branch July 21, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL read timeout ignores query timeout

1 participant