LuaSQL and Database Drivers: Connection Pool Saturation Visibility
0 reputation · 27 Jun 2023, 20:45 UTC
0 reputation · 27 Jun 2023, 20:45 UTC
LuaSQL provides an implicit connection pooling mechanism designed to reuse database connections across a session. However, the current API does not expose the internal state of the pool or provide a method to define hard limits on the number of concurrent connections maintained by the driver.
This lack of visibility creates uncertainty when diagnosing intermittent connection exhaustion. Because Lua's garbage collector may close idle connections unpredictably, it is difficult to determine if a failure to acquire a connection is due to pool saturation, an external database server limit, or an aggressive GC cycle.
No to both. LuaSQL's documented API — the environment, connection, and cursor objects — has no method to query active connection counts and no option to set a pool size, because LuaSQL does not implement a connection pool. Each env:connect() call opens a fresh connection through the underlying native client library (libpq, libmysqlclient, sqlite3, ODBC, OCI, depending on the driver). There is no internal pool state to expose and no implicit limit to configure.
Confirmed from the documented API surface:
luasql.mysql()) returning an environment, env:connect(...) returning a connection, conn:execute() returning a cursor, each with a close() method, plus the luasql._VERSION string. No pooling or introspection functions appear anywhere in that surface.conn:close() releases a connection explicitly. If you skip it, the connection is reclaimed only when the garbage collector finalizes the userdata, and that timing is nondeterministic — GC is not a release mechanism you can rely on.The likely explanation, which I cannot confirm from your environment: the "implicit pooling" description comes from a framework or hosting layer built on top of LuaSQL, not from LuaSQL itself. The intermittent pattern fits connections opened per operation and not closed on every code path, including error paths. Live connections then accumulate until GC finalizes some of them — or until the server's max_connections or a per-user cap is hit, which can mimic pool saturation exactly.
print(luasql._VERSION) in the failing environment. I could not verify a 1.0.x LuaSQL release line with pooling; the maintained Kepler releases are the 2.x line, and the description above applies to that documented API. If _VERSION reports something unexpected, the pooling claim belongs to whatever wraps LuaSQL.local open_count = 0
local function connect(env, ...)
local conn, err = env:connect(...)
if conn then open_count = open_count + 1 end
return conn, err
end
local function release(conn, cur)
if cur then cur:close() end
if conn then conn:close(); open_count = open_count - 1 end
end
Call release on every path, including inside pcall error handling, and close cursors too — open cursors hold server-side resources and can contribute to exhaustion independently of the connection count.
SHOW PROCESSLIST on MySQL or SELECT count(*) FROM pg_stat_activity; on PostgreSQL. If the server sees more connections than your counter, another component is connecting; if the counts match and are high, it is client-side accumulation.collectgarbage('collect') periodically. If exhaustion disappears, unclosed connections awaiting finalization are the cause — fix the missing closes rather than tuning GC.Is the Lua state long-lived, or does your host spawn a fresh state per request? In a long-lived state, a wrapper counter plus disciplined closes usually resolves this. If a new state is created per request, no state-level pool can persist across requests and an external pooler is typically the right fix. Knowing which component claims to pool connections would also pin down where any size limit actually lives.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.