logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dimitry Declercq (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (LOG4J2-438) JDBCDatabaseManager does not send commit command
Date Wed, 20 Nov 2013 10:18:35 GMT

    [ https://issues.apache.org/jira/browse/LOG4J2-438?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13827512#comment-13827512
] 

Dimitry Declercq commented on LOG4J2-438:
-----------------------------------------

I've added a few lines of code to JDBCDatabaseManager to fix this issue. This is a quickfix
and is probably not good enough for use in the GA, especially since this doesn't cover the
use-case when a buffer is used.

{code:title=JDBCDatabaseManager.java}
    @Override
    protected void writeInternal(final LogEvent event) {
            ...
            if (this.statement.executeUpdate() == 0) {
                throw new AppenderLoggingException("No records inserted in database table
for log event in JDBC manager.");
            }
            // commit should only be called explicitly when autoCommit is disabled
            if (!this.connection.getAutoCommit()) {
                this.connection.commit();
            }
{code}

For the usecase with buffers the quickest way would be to add a commit hook in AbstractDatabaseManager
which the JDBCDatabaseManager implements. I've not written this actual code (only in my head)
and this should be consider a brainfart:
{code:title=AbstractDatabaseManager.java}
    public final synchronized void flush() {
        if (this.isConnected() && this.buffer.size() > 0) {
            for (final LogEvent event : this.buffer) {
                this.writeInternal(event);
            }
            this.commit();
            this.buffer.clear();
        }
    }

    protected void commit() {
        //Dummy implementation
    }
{code}

{code:title=JDBCDatabaseManager.java}
    protected void commit() {
        try {
            // commit should only be called explicitly when autoCommit is disabled
            if (!this.connection.getAutoCommit()) {
                this.connection.commit();
            }
        } catch (final SQLException e) {
            LOGGER.error("Could not send commit to database for [{}].", this.getName(), e);
        }
    }
{code}

> JDBCDatabaseManager does not send commit command
> ------------------------------------------------
>
>                 Key: LOG4J2-438
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-438
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Appenders
>    Affects Versions: 2.0-beta9
>         Environment: Java 7u45, Windows, H2
>            Reporter: Ralph Schaer
>            Assignee: Nick Williams
>            Priority: Minor
>
> I'm fiddling with the log4j jdbc appender and found an issue with datasources that have
the flag defaultAutoCommit set to false. With such datasources the application has to call
the method connection.commit() after an update statement, if omitted nothing will be updated
or inserted in the database.
> That is the problem with the class JDBCDatabaseManager. It executes the statement (with
this.statement.executeUpdate()) but does not call commit. Nothing is inserted if the defaultAutoCommit
flag of the datasource is set to false. 
> One possible solution is to check the autoCommit flag of the datasource and call commit
when it's set to false.
> if (this.statement.executeUpdate() == 0) {
>   throw new AppenderLoggingException(
>    "No records inserted in database table for log event in JDBC manager.");
> }
> 			
> if (!this.connection.getAutoCommit()) {
>   this.connection.commit();
> }
> Maybe this has to be done differently when a buffer is used. The method AbstractDatabaseManager.flush
should only call commit after the loop. 
>         if (this.isConnected() && this.buffer.size() > 0) {
>             for (final LogEvent event : this.buffer) {
>                 this.writeInternal(event);
>             }
>            if (!connection.getAutoCommit()) {
>               connection.commit();
>            }
>             this.buffer.clear();
>         }
> Or maybe using the batch methods of jdbc would improve the performance even more
> if (this.isConnected() && this.buffer.size() > 0) {
>   for (final LogEvent event : this.buffer) {
>     //create statement .......
>     statement.addBatch()
>   }
>   statement.executeBatch();
>   if (!connection.getAutoCommit()) {
>     connection.commit();
>   }
>   this.buffer.clear();
> }



--
This message was sent by Atlassian JIRA
(v6.1#6144)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Mime
View raw message