Ustaliliśmy przyczynę tego problemu. Wyjaśnia to błędna implementacja setQueryTimeout() w najnowszych sterownikach JDBC 9.2-100x. Może się to nie zdarzyć, jeśli ręcznie otworzysz/zamkniesz połączenie, ale bardzo często zdarza się to przy włączonej puli połączeń i automatycznym zatwierdzaniu ustaw fałsz . W takim przypadku należy wywołać setQueryTimeout() z wartością niezerową (na przykład przy użyciu adnotacji @Transactional( timeout =xxx ) frameworka Spring).
Okazuje się, że ilekroć podczas wykonywania instrukcji zostanie zgłoszony wyjątek SQL, licznik czasu anulowania nie został anulowany i pozostaje aktywny (tak jest zaimplementowany). Z powodu buforowania połączenie za nie jest zamykane, ale jest zwracane do puli. Później, po wyzwoleniu zegara anulowania, losowo anuluje zapytanie aktualnie skojarzone z połączeniem, z którym ten zegar został utworzony. W tej chwili jest to zupełnie inne zapytanie, które wyjaśnia efekt losowości.
Sugerowanym obejściem tego problemu jest rezygnacja z setQueryTimeout() i użycie konfiguracji PostgreSQL (statement_timeout). Nie zapewnia tego samego poziomu elastyczności, ale przynajmniej zawsze działa.