[
https://issues.apache.org/jira/browse/HIVE-29584?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
ASF GitHub Bot updated HIVE-29584:
----------------------------------
Labels: datanucleus hikaricp hms metastore mysql pull-request-available
threadlocal (was: datanucleus hikaricp hms metastore mysql threadlocal)
> ObjectStore.handleDirectSqlError() leaks broken JDBC connection wrapper in PM
> ThreadLocal cache after MySQL transient outage
> ----------------------------------------------------------------------------------------------------------------------------
>
> Key: HIVE-29584
> URL: https://issues.apache.org/jira/browse/HIVE-29584
> Project: Hive
> Issue Type: Bug
> Components: Metastore, Standalone Metastore
> Affects Versions: 3.1.3, 4.0.0, 4.2.0
> Environment: Hive: 3.1.3 (also verified affected: 4.0.0, 4.1.0)
> Standalone Metastore: yes
> Backend DB: MySQL 8.0
> JDBC Driver: mysql-connector-j 8.0.30
> Connection Pool: HikariCP 2.6.1
> ORM: DataNucleus 4.1.19 + datanucleus-core 4.1.17 + datanucleus-api-jdo
> 4.2.4
> JVM: OpenJDK 1.8.0_412
> Affected Client: Apache Amoro (long-lived thrift connection client)
> Reporter: soowan4147
> Priority: Critical
> Labels: datanucleus, hikaricp, hms, metastore, mysql,
> pull-request-available, threadlocal
>
> #
> ## Summary
> After a brief MySQL outage (e.g., 4-second network glitch from a planned
> DBA operation), one HMS Thrift worker thread can permanently retain a broken
> HikariProxyConnection in its ObjectStore.pm ThreadLocal cache, leading to
> indefinite reuse of the same broken wrapper for hours until HMS is
> restarted.
> ## Root Cause
> `MetaStoreDirectSql.prepareTxn()` executes `SET
> @@session.sql_mode=ANSI_QUOTES`
> on every transaction. When this fails on a broken connection (e.g.,
> "Connection is closed" SQLException after MySQL transient outage),
> `ObjectStore.handleDirectSqlError()` falls back to ORM mode but does NOT
> invalidate the PersistenceManager. As a result:
> 1. Same `ObjectStore.pm` is reused on next RPC
> 2. Same broken HikariProxyConnection wrapper is reused (held via
> ThreadLocal)
> 3. HikariCP cannot evict the in-use connection per design
> 4. Only HMS restart releases the wrapper
> ## Production Incident Evidence (2026-04-26)
> - pool-6-thread-93872 retained broken wrapper for ~5 hours
> - 41,302 audit RPCs all from same client IP, all failing with same error
> - 6,047 "Falling back to ORM" + 14,309 ERROR logs in 5 hours
> - master02 normal threads' RPC throughput dropped 90%+ during incident
> - catalogd's ALTER_TABLE processing stalled 1~3 minutes per event
> - Resolved only by master HMS restart (3h 10m total impact)
> ## Source References
> Verified the defect exists in:
> - 3.1.3: `ObjectStore.java#L3646-L3697` (handleDirectSqlError)
> - 4.0.0: `ObjectStore.java#L4449-L4495` (same defect, no PM cleanup)
> - `MetaStoreDirectSql.java#L2026-L2034` (prepareTxn trigger)
> ## Steps to Reproduce
> 1. Set up HMS 3.1.3+ with HikariCP backed by MySQL
> 2. Create a long-lived metastore client that maps permanently to one HMS
> worker thread (e.g., Apache Amoro pod, Spark Thrift Server)
> 3. Briefly disconnect MySQL (4 seconds via iptables drop or KILL CONNECTION)
> 4. Observe: one worker thread continues to reuse the broken wrapper
> indefinitely
> 5. Verify: log shows continuous "Falling back to ORM path due to direct SQL
> failure: Error setting ansi quotes: Connection is closed" from same
> thread
> ## Proposed Fix
> In `ObjectStore.handleDirectSqlError()`, when the cause is a
> connection-level
> SQLException, invalidate the PM:
> ```java
> if (isConnectionLevelError(ex)) {
> if (pm != null) {
> try {
> if (pm.currentTransaction().isActive())
> { pm.currentTransaction().rollback(); }
> pm.close(); // releases HikariCP wrapper to pool
> } catch (Exception e)
> { // best effort }
> pm = null;
> directSql = null;
> }
> }
> This forces a fresh PM (and thus a fresh connection) on the next RPC,
> allowing the broken connection to be properly evicted by HikariCP.
> Workarounds (currently in use)
> - Client-side: shorten hive.metastore.client.socket.timeout on long-lived
> clients (e.g., Amoro) so they auto-reconnect every few minutes, breaking
> the permanent thread mapping
> - Operational: enable HikariCP leakDetectionThreshold, alarm on
> "Connection leak detection triggered" log, and auto-restart the affected HMS
> Related JIRAs (none directly fix this)
> - HIVE-22804 (sessionVariables workaround) — does not prevent the leak
> - HIVE-20192 (PM cleanup at thread exit) — different mechanism
> - HIVE-28788 (commit failure → starvation) — different trigger
> - HIVE-28839 (DataNucleus connection starvation) — different code path
> To my knowledge, this specific defect (PM ThreadLocal retaining broken
> wrapper after SQLException in handleDirectSqlError) has not been reported
> before.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)