Abbiamo scoperto la causa di questo problema. È spiegato dall'implementazione difettosa di setQueryTimeout() negli ultimi driver JDBC 9.2-100x. Potrebbe non accadere se apri/chiudi la connessione manualmente, ma molto spesso accade con il pool di connessioni in atto e autocommit impostato su falso . In questo caso, setQueryTimeout() dovrebbe essere chiamato con un valore diverso da zero (ad esempio, utilizzando l'annotazione Spring Framework @Transactional( timeout =xxx )).
Si scopre che ogni volta che viene sollevata un'eccezione SQL durante l'esecuzione dell'istruzione, il timer di annullamento non è stato annullato e rimane attivo (è così che viene implementato). A causa del pool, la connessione dietro non viene chiusa ma viene restituita al pool. Successivamente, quando si attiva il timer di annullamento, annulla in modo casuale la query attualmente associata alla connessione con cui è stato creato questo timer. In questo momento, è una query completamente diversa che spiega l'effetto di casualità.
La soluzione alternativa suggerita è rinunciare a setQueryTimeout() e utilizzare invece la configurazione di PostgreSQL (statement_timeout). Non fornisce lo stesso livello di flessibilità ma almeno funziona sempre.