Как установить тайм-аут getConnection() для c3p0?

Вчера AWS RDS снизился - и наша база данных тоже.

Когда это произошло, C3P0 попытается получить соединение с базой данных и будет висеть. Мне явно хотелось бы, чтобы мое приложение возвращало страницу ошибок в этих экземплярах, а не просто ожидало ответа.

Вот что выглядит код:

ComboPooledDataSource db = new ComboPooledDataSource();
...
Connection conn = db.getConnection();

Как установить тайм-аут для получения соединения из пула соединений c3p0?

Я думал, что checkoutTimeout() будет, но это не так. Это "количество миллисекунд, вызываемых клиентом getConnection(), будет ждать подключения, которое будет проверено или приобретено, когда пул будет исчерпан". Поскольку пул не исчерпан (он просто недоступен), это не применяется.

Я также думал, что setAcquireRetryAttempts и setAcquireIncrement будут работать, но они не работают, так как соединение не прерывается, оно просто не отвечает.

Когда я вытащил весь стек, здесь он кидается:

SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int) line: not available [native method]    
SocketInputStream.read(byte[], int, int) line: 129  
ReadAheadInputStream.fill(int) line: 113    
ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(byte[], int, int) line: 160    
ReadAheadInputStream.read(byte[], int, int) line: 188   
MysqlIO.readFully(InputStream, byte[], int, int) line: 2428 
MysqlIO.reuseAndReadPacket(Buffer, int) line: 2882  
MysqlIO.reuseAndReadPacket(Buffer) line: 2871   
MysqlIO.checkErrorPacket(int) line: 3414    
MysqlIO.sendCommand(int, String, Buffer, boolean, String) line: 1936    
MysqlIO.sqlQueryDirect(StatementImpl, String, String, Buffer, int, int, int, boolean, String, Field[]) line: 2060   
JDBC4Connection(ConnectionImpl).execSQL(StatementImpl, String, int, Buffer, int, int, boolean, String, Field[], boolean) line: 2542 
JDBC4PreparedStatement(PreparedStatement).executeInternal(int, Buffer, boolean, boolean, Field[], boolean) line: 1734   
JDBC4PreparedStatement(PreparedStatement).executeQuery() line: 1885 
NewProxyPreparedStatement.executeQuery() line: 76   
C3P0PooledConnectionPoolManager.initializeAutomaticTestTable(String, DbAuth) line: 799  
C3P0PooledConnectionPoolManager.createPooledConnectionPool(DbAuth) line: 696    
C3P0PooledConnectionPoolManager.getPool(DbAuth) line: 257   
C3P0PooledConnectionPoolManager.getPool() line: 271 
ComboPooledDataSource(AbstractPoolBackedDataSource).getNumThreadsAwaitingCheckoutDefaultUser() line: 203    
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
Method.invoke(Object, Object...) line: 597  
BeansUtils.extractAccessiblePropertiesToMap(Map, Object, Collection) line: 359  
BeansUtils.appendPropNamesAndValues(StringBuffer, Object, Collection) line: 324 
ComboPooledDataSource.toString() line: 539  
ComboPooledDataSource(AbstractPoolBackedDataSource).getPoolManager() line: 462  
ComboPooledDataSource(AbstractPoolBackedDataSource).getConnection() line: 128   

Когда я googled "socketRead0 timeout" и "socketRead0 hang" - я вижу много проблем, но никаких реальных решений.

Есть ли способ заставить период ожидания здесь?

Спасибо!

Ответ 1

Проблема заключается в MySQL ReadAheadInputStream, который использует блокировку чтения. Родной сокет заблокирован и никогда (?) Не возвращает код ошибки. Так что соединение тоже висит.

Я не вижу способа справиться с этим, не помещая ваш код в поток и присоединяю() к нему с тайм-аутом. Я не верю, хотя проблема оправдывает осложнения: я надеюсь, что Amazon сделает правильные выводы из времени простоя и не допустит повторения этого события.

Ответ 2

Ну, вы можете назначить queryTimeout на уровне соединения. IIRC, MySQL действительно подчиняется этому. Dunno, если C3P0 понравится, но это может сработать.