Bug #54367 | Prepared statement batch insertion loss | ||
---|---|---|---|
Submitted: | 9 Jun 2010 13:44 | Modified: | 17 Sep 2012 8:10 |
Reporter: | RICHARDS PETER | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | Connector / J | Severity: | S3 (Non-critical) |
Version: | 5.1.41-community | OS: | Linux (ubuntu 2.6.28-11-generic) |
Assigned to: | Alexander Soklakov | CPU Architecture: | Any |
[9 Jun 2010 13:44]
RICHARDS PETER
[9 Jun 2010 13:47]
Tonci Grgin
Hi Peter and thanks for your report. Would you mind attaching small but complete test case (incl connection string, DML/DDL) so I can check.
[9 Jun 2010 14:04]
Mark Matthews
Are you sure you're not swallowing an exception somewhere, or ignoring warnings? We know of know cases where the driver is "losing" batch statements, but if you're not checking the return values of executeBatch(), or ignoring any exceptions, or warnings, it very well could be that some of your rows had errors, or were converted to existing rows, depending on how they were inserted.
[9 Jun 2010 14:05]
RICHARDS PETER
The scenario can be reproduced using a test case like this. This scenario is with respect to the project I work on. 1) Create a JMS queue producer that writes an Object message into a queue. The object message should contain the appropriate parameters for database insertion like the id, the byte[] for insertion, etc. 2) Create a JMS queue producer that consumes messages from the queue. When we get a message in the message consumer, set the message parameters into the PreparedStatement and add it to the batch. Log this with a statement so that we can find the total number of additions into the batch. When the batch size becomes the configured value try executing the batch and commit. Log this preStmtSaveRequest.executeBatch().length so that we can find the number of total insertions. Set the timeStamp with currentTime as I said in the above description. 3) Span a new thread that performs this commit operation when the configured time is reached. Set the timeStamp with currentTime and set the batchSize as 0 at the time of commit operation. 4) Try pushing messages to the queue at a high rate. Start the listeners also. Find the record count difference in logs and database.
[9 Jun 2010 14:13]
RICHARDS PETER
Yes I am sure that I am not swallowing any Exceptions. If any Exceptions are thrown I log them into the file with the parameters. But I did not find any Exceptions in the log. I had a similar experience earlier when I tried to insert a String value into the database using the prepared statement. There instead of the BLOB data type I used varchar. At that time we switched to normal Statment object in java. Due to time constraints we avoided the String value in the database. If the query has any ' character in any of the varchar value we won't be allowed to insert it using normal Statment right. So in that particular case we thought of logging them in the file instead of insertion into the database. But this experience with BLOB object is critical in our project. We need a solution for that.
[9 Jun 2010 15:17]
Mark Matthews
Without seeing exactly how you're writing to the database (your java code), and your schema, it's hard to say what's going on. I'm not sure there's a bug in the JDBC driver here, only because I know there are millions of rows inserted into MySQL databases via JDBC this way every hour without issues (I work on an application myself that does just that). If there is a bug, it's specific to your use case, and a simple description doesn't allow us to reproduce the issue so that we can fix it for you. Can you show us a testcase (in code) that doesn't rely on JMS, etc. and just does the inserts the exact same way your application does which reproduces the problem you're experiencing?
[10 Jun 2010 9:40]
RICHARDS PETER
The problem comes in my project when I create a PreparedStatement instance and the Statement instance from the same Connection instance. Then I use the PreparedStatement batch and the Statement batch to add the records simultaneously into the tables using the same Connection . I am not sure if I am going wrong somewhere in the code. My project's code might look similar to the attachment. The attached code can create reproduce the issue. It could be the problem with the logic I follow to execute the task. Please let me know if I am going wrong somewhere. Richards.
[10 Jun 2010 9:42]
RICHARDS PETER
I am attaching the table structure and the java code require. Please use mysql-connector-java-5.1.12-bin.jar file also in cp
Attachment: Connector.zip (application/zip, text), 354.52 KiB.
[10 Jun 2010 12:14]
RICHARDS PETER
I am attaching a java code with not much threading that can still produce the issue. Let me know where I went wrong.
Attachment: PreInsert.java (text/x-java), 7.48 KiB.
[11 Jun 2010 5:03]
RICHARDS PETER
Hi Tonci and Mark, Any update on this issue?
[14 Jun 2010 5:58]
RICHARDS PETER
Hi all, I made a change in my code. It seems like it was my code that created the problem. I made some synchronization on the prepared statement and the statement variables when I added queries to the batch and executed the batch. This issue never appeared with the Statement instance. I never lost any messages though they were used by multiple threads. Just tell me if this synchronization is mandatory. I am attaching the src code. Richards.
[14 Jun 2010 5:59]
RICHARDS PETER
Modified code with synchronization that solved the issue.
Attachment: PreInsert.java (text/x-java), 7.65 KiB.