jeudi 18 février 2010

Mode curseur et transactions avec JDBC (PostgresQL)

Lorsque l'on travaille en mode curseur sous JDBC, le mode auto-commit du connecteur est nécessairement dévalidé:

connection.setAutoCommit(false);

La conséquence est que le postmaster garde en mémoire le log des requêtes.
Si l'on fait plusieurs requêtes avec le même connecteur JDBC, on reste connecté au même Postmaster et ce dernier explose en mémoire.

J'ai essayé d'insérer des commits entre les requêtes, mais cela a produit l'erreur suivante:

DECLARE CURSOR pourrait seulement être utilisé dans des blocs de transaction

J'avoue en pas très bien comprendre le sens de ce message et je me suis résolu à créer un nouveau connecteur à chaque requête en mode curseur:


public static ResultSet runLargeQuerySQL(String sql) throws FatalException {
try {
closeLargeQueryConnection();
jdbc_large_connection = DriverManager.getConnection(Database.getConnector().getJdbc_url(),Database.getConnector().getJdbc_reader(), Database.getConnector().getJdbc_reader_password());
Statement _stmts =jdbc_large_connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
jdbc_large_connection.setAutoCommit(false);
_stmts.setFetchSize(1000);
if( Messenger.debug_mode ) Messenger.printMsg(Messenger.DEBUG, "Select large query: " + sql);
/*
* Trailing semicolumns make the statement to run in non-cursor mode
*/
return _stmts.executeQuery(sql.replaceAll(";", ""));
} catch (Exception e) {
Messenger.printMsg(Messenger.ERROR, "Query: " + sql);
Messenger.printStackTrace(e);
FatalException.throwNewException(SaadaException.DB_ERROR, e);
}
return null;
}

/**
* @throws SQLException
*/
public static void closeLargeQueryConnection() throws SQLException {
if( jdbc_large_connection != null ) {
if( Messenger.debug_mode ) Messenger.printMsg(Messenger.DEBUG, "Close connection for large queries ");
jdbc_large_connection.close();
jdbc_large_connection = null;
}

}

Aucun commentaire: