VTTablet: pooled-connection baseline is inconsistent between fresh and settings-reset connections on servers using init_connect
Overview of the Issue
Spun out of the review of #21062 (see this thread), raised by @arthurschreiber.
A pooled vttablet connection can be in one of two "clean" states, and they differ on a server that uses init_connect:
- Fresh: after the handshake, MySQL runs
init_connectfor non-admin users (vt_appwithoutSUPER/CONNECTION_ADMIN), so the session carries whatever it set — e.g.time_zone,transaction_isolation, runtimesql_modemembers. Vitess then runssqlmode.NeutralizeSessionQuery, which deliberately sources from the session value to preserve those adjustments (go/vt/dbconfigs/dbconfigs.go). - Returned from the settings pool: a connection that carried a client
Settingis reset with the queryBuildSettingQuerygenerates (go/vt/vttablet/tabletserver/planbuilder/plan.go), which isSET <name> = DEFAULTfor every variable exceptsql_mode.DEFAULTresolves to the global value, not theinit_connectvalue, so theinit_connectadjustment for that variable is gone. (sql_modewas special-cased tosqlmode.NeutralizedGlobalExpr, which also sources from the global.)
So today, whether a pooled connection reflects init_connect depends on its history. #21062 did not change this — closing a connection after CALL yields a fresh connection, one of the two existing states — but the review surfaced it.
Impact
Operators who rely on init_connect to set per-session defaults for the app user get them on some pooled connections and not others, silently. Anyone not using init_connect (or whose app user is exempt from it) is unaffected.
Options discussed
- Define the baseline as the post-reset (globals) state for every connection, e.g. run
COM_RESET_CONNECTION(or equivalent) as part of connection setup, so fresh and reset connections match. Consistent, but it means deliberately discardinginit_connectfor all pooled connections — a behavior change for operators relying on it, and it would need a documented migration path (move those settings to globals or--init-file). Note a reset immediately after connect also does not touch the handshake-negotiated charset, which is the correct outcome here. - Define the baseline as the fresh state, and make the settings-pool reset restore it — e.g. capture each reset variable's post-
init_connectsession value at connect time and reset to that instead ofDEFAULT. Preservesinit_connect, at the cost of per-connection bookkeeping per settable variable. - Document the drift as a known limitation of combining
init_connectwith vtgate session settings.
Whichever way, it should be decided deliberately rather than as a side effect of a bug fix.
Reproduction Steps
- Start mysqld with
init_connect = "SET SESSION time_zone='+05:30'"and avt_appuser withoutSUPER/CONNECTION_ADMIN. - Through vtgate, on connection A:
select @@session.time_zone→+05:30(fresh pooled connection). - On connection B:
set @@session.time_zone = '+01:00'(puts the connection in the settings pool), run a query, then close B so the connection is reset and returned. - Repeat step 2 until the read lands on the reset connection →
SYSTEM(the global), not+05:30.
Binary Version
main; the code path is present on the supported release branches.
Related
This is one of a set of changes that came out of one investigation into what a stored procedure, or any statement whose tables the planner never sees, can do on a vttablet. They reference each other so the whole picture is reachable from any one of them.
Table ACL — GHSA-w6mx-2f8x-pqf4
- #21053 — fail closed under strict table ACL for statements whose tables the parser discards (
DO,CALL,REPAIR,OPTIMIZE,LOAD DATA) - #21139 — stacked on #21053: check the reads embedded in statements the planner does parse (
CREATE TABLE ... AS SELECT,EXPLAIN ANALYZE,SHOW ... WHERE,SET), reject connection settings that carry a subquery, and have a targeted vtgate session store aSET's value rather than its expression - #21134 — still open: a stored function invoked inside an expression runs its body outside the table ACL
- #21138 — still open: parse the
CREATE TABLEsource forms the grammar only partially accepts, which #21139 has to deny outright today - #21140 — still open:
ALTER/REVERT VITESS_MIGRATIONderive no permissions, so any authenticated caller can control Online DDL migrations; split out of #21053's review
Stored-procedure session residue
- #21046 — procedure-body session state (
SET SESSION, temp tables) persists on pooled connections afterCALL - #21062 — fixes #21046 by discarding the pooled connection after
CALL - #21063 — still open: the same residue on a transaction connection recycled at commit
- #21066 — (this issue) still open: the pooled-connection baseline differs between fresh and settings-reset connections on servers using
init_connect
Source: vitessio/vitess