Issue Details (XML | Word | Printable)

Key: JDBC-411
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Mark Rotteveel
Reporter: Attila Molnár
Votes: 0
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
Jaybird JDBC Driver

BLOB not found

Created: 16/Oct/15 12:17 PM   Updated: 11/Jan/20 11:59 AM
Component/s: JDBC driver
Affects Version/s: Jaybird 2.2.8
Fix Version/s: None

File Attachments: 1. Zip Archive JDBC-402.ZIP (154 kB)

Environment: 2.5.4, x64, SuperClassic, Windows


 Description  « Hide
Hi Mark!

On one [read-write, read-commited] thread I update a blob column in a record. On an other [read, read-commited] thread I read that record from DB. The two thread are concurrent read and write can occure on the same time. Sometimes I get "BLOB" not found error.
It looks like this problem : http://www.lnssoftware.ca/blog/?p=67

Is this a JayBird bug, or Firebird bug?
Using [read, snapshot] transaction on the reader thread could solve the problem?



Thank you!

 All   Comments   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Mark Rotteveel added a comment - 16/Oct/15 02:59 PM
Could you create a reproduction case, that makes it easier to analyze.

Attila Molnár added a comment - 19/Oct/15 11:50 AM
Hi!

Here is my test program.
Unfortunatly this in itself cannot reproduce the error for me but maybe for you.
BUT running the test and run "select * from test" with IBExpert in [read, read-commited] it shows the same BLOB not found error. When I switch to [read, snapshot] transaction in IBExpert the error disappears.
So this looks like an error in the FB engine itself freeeing blob id too soon.


public class JDBC402 {


public class DBThread extends Thread {

protected BasicDataSource ds;
protected Connection conn;

public DBThread()
throws SQLException {

super();
ds = new BasicDataSource();
ds.setUrl("jdbc:firebirdsql:l3s-server/3051:d:\\jdbc-402.fdb?charSet=UTF-8&isc_dpb_sql_dialect=1");
ds.setUsername("SYSDBA");
ds.setPassword("masterkey");
ds.setMaxIdle(-1);
ds.setDefaultAutoCommit(false);
ds.setDefaultReadOnly(true);
ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
conn = ds.getConnection();
start();
}
}

public class ThreaRead extends DBThread {

Integer id;
String data;

public ThreaRead()
throws SQLException {

super();
}

@Override
public void run() {

try {
while (!interrupted()) {
conn.setAutoCommit(false);
conn.setReadOnly(true);
FirebirdConnection fc = (FirebirdConnection) conn.unwrap(FirebirdConnection.class);
TransactionParameterBuffer tpb = fc.createTransactionParameterBuffer();
tpb.addArgument(TransactionParameterBuffer.READ);
tpb.addArgument(TransactionParameterBuffer.READ_COMMITTED);
tpb.addArgument(TransactionParameterBuffer.REC_VERSION);
tpb.addArgument(TransactionParameterBuffer.NOWAIT);
fc.setTransactionParameters(tpb);
Statement s = fc.createStatement();
try (ResultSet rs = s.executeQuery("SELECT id, data FROM test")) {
while (rs.next()) {
id = new Integer(rs.getInt(1));
data = new String(rs.getString(2));
}
}
conn.commit();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

public class ThreaWrite extends DBThread {

public ThreaWrite()
throws SQLException {

}

@Override
public void run() {

try {
while (!interrupted()) {
int i = 1;
while (i <= 160) {
conn.setAutoCommit(false);
conn.setReadOnly(false);
FirebirdConnection fc = (FirebirdConnection) conn.unwrap(FirebirdConnection.class);
TransactionParameterBuffer tpb = fc.createTransactionParameterBuffer();
tpb.addArgument(TransactionParameterBuffer.WRITE);
tpb.addArgument(TransactionParameterBuffer.READ_COMMITTED);
tpb.addArgument(TransactionParameterBuffer.REC_VERSION);
tpb.addArgument(TransactionParameterBuffer.NOWAIT);
fc.setTransactionParameters(tpb);
PreparedStatement s = conn.prepareStatement("UPDATE test SET data = ? WHERE id = ?");
s.setObject(1, new Date().toString());
s.setObject(2, i);
s.execute();
conn.commit();
i++;
}
}
}
catch (SQLException e) {
e.printStackTrace();
}
}
}


public JDBC402()
throws SQLException,
InterruptedException {

ThreaRead read = new ThreaRead();
ThreaWrite write = new ThreaWrite();
while (!read.interrupted())
Thread.sleep(1);
while (!write.interrupted())
Thread.sleep(1);
}


public static void main(
String[] args)
throws Throwable {

JDBC402 app = new JDBC402();
}
}

Attila Molnár added a comment - 19/Oct/15 12:07 PM
The call stack in the application :

hu.libra.lreserver.process.ProcessException: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544382. BLOB not found
hu.libra.lreserver.process.ProcessException: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544382. BLOB not found
at hu.libra.lreserver.jobs.async.ReportJob$ReportJobTask.trySetState(ReportJob.java:620)
at hu.libra.lreserver.process.AbstractProcess.finished(AbstractProcess.java:264)
at hu.libra.lreserver.process.AbstractProcess$1.run(AbstractProcess.java:237)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hu.libra.lreserver.wrappers.autocloseable.ExecutorWithThread$ExecutorThread.run(ExecutorWithThread.java:59)
Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544382. BLOB not found
at org.firebirdsql.jdbc.FBStatementFetcher.fetch(FBStatementFetcher.java:176)
at org.firebirdsql.jdbc.FBStatementFetcher.next(FBStatementFetcher.java:97)
at org.firebirdsql.jdbc.AbstractResultSet.next(AbstractResultSet.java:285)
at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191)
at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191)
at hu.libra.commons.db.resultset.ConverterResultSet.next(ConverterResultSet.java:126)
at hu.libra.commons.db.resultset.PartitionedResultSet.next(PartitionedResultSet.java:105)
at hu.libra.lrecommons.objects.RptReportDataView.<init>(RptReportDataView.java:45)
at hu.libra.lrecommons.objects.RptReportJob.<init>(RptReportJob.java:51)
at hu.libra.lrecommons.utils.DBUtilsRead.selectRptReportJob(DBUtilsRead.java:1303)
at hu.libra.lrecommons.utils.DBUtilsRead.selectRptReportJob(DBUtilsRead.java:1322)
at hu.libra.lreserver.storage.RptReportJobList.refreshReportJob(RptReportJobList.java:95)
at hu.libra.lreserver.jobs.async.ReportJob$ReportJobTask.cacheRefresh(ReportJob.java:518)
at hu.libra.lreserver.jobs.async.ReportJob$ReportJobTask.trySetState(ReportJob.java:607)
... 5 more
Caused by: org.firebirdsql.gds.GDSException: BLOB not found
at org.firebirdsql.gds.impl.wire.AbstractJavaGDSImpl.readStatusVector(AbstractJavaGDSImpl.java:2092)
at org.firebirdsql.gds.impl.wire.AbstractJavaGDSImpl.receiveResponse(AbstractJavaGDSImpl.java:2042)
at org.firebirdsql.gds.impl.wire.AbstractJavaGDSImpl.iscDsqlFetch(AbstractJavaGDSImpl.java:1322)
at org.firebirdsql.gds.impl.GDSHelper.fetch(GDSHelper.java:272)
at org.firebirdsql.jdbc.FBStatementFetcher.fetch(FBStatementFetcher.java:171)
... 18 more

Mark Rotteveel added a comment - 19/Oct/15 01:36 PM
Thanks, I will see if I can reproduce this after I get 2.2.9 out the door. I have two theories: either the new blob id is selected and not yet considered visible to the transaction when opening the blob, or the old blob id is already garbage collected even though the transaction might still have an interest. Playing around with the fetch size might have an effect on the reproducibility. I will see if I can narrow it down and report a bug on CORE if necessary.

Mark Rotteveel added a comment - 19/Oct/15 01:44 PM - edited
One last question: Which Firebird version do you use (version + type (classic, superclassic, superserver))?

Attila Molnár added a comment - 21/Jan/16 07:46 AM
CORE-5078 might be related?

Mark Rotteveel added a comment - 21/Jan/16 08:36 AM - edited
It might be. But I see you use SuperClassic, not sure if that makes a difference here though.

Attila Molnár added a comment - 22/Jan/16 08:14 AM
Tested with latest 2.5.6. snapshot which has CORE-5078 fix.
The problem still occures, not the same case. (This is a concurrency problem, that was not)

Attila Molnár added a comment - 22/Jan/16 08:16 AM
I think this is a CORE/engine problem not JDBC.

Mark Rotteveel added a comment - 23/Mar/16 09:51 AM
I haven't yet found the exact combination that triggers it. I was able to trigger it from flamerobin when running your sample application, so it looks like it is indeed a problem (expected?) of the engine, and not Jaybird itself.

Attila Molnár added a comment - 13/Feb/17 02:51 PM
I got same error when the reader thread Connection/transaction is in [read, snapshot] mode
So snapshot is not a solution to this problem just a very effective, but not 100% percent working workaround. (Nearly 1 year passed and I just got this error for the first time)