Skip to content

NullPointerException when executing batch insert for 2.2.224/3 #3960

@NotOsprey

Description

@NotOsprey

Hi,when I use batch insert (10000 record per batch && commit) , sometime will occur follow exception at 2.2.224
org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: java.lang.NullPointerException [2.2.224/3]" [50000-224]
at org.h2.message.DbException.get(DbException.java:212)
at org.h2.message.DbException.convert(DbException.java:407)
at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
at org.h2.mvstore.MVStore.panic(MVStore.java:371)
at org.h2.mvstore.MVStore.tryExecuteUnderStoreLock(MVStore.java:941)
at org.h2.mvstore.RandomAccessStore.doHousekeeping(RandomAccessStore.java:723)
at org.h2.mvstore.FileStore.writeInBackground(FileStore.java:1837)
at org.h2.mvstore.FileStore$BackgroundWriterThread.run(FileStore.java:2248)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: java.lang.NullPointerException [2.2.224/3]" [50000-224]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
... 9 more
Caused by: org.h2.mvstore.MVStoreException: java.lang.NullPointerException [2.2.224/3]
at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
... 4 more
Caused by: java.lang.NullPointerException
at org.h2.mvstore.FileStore.getToC(FileStore.java:2056)
at org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1906)
at org.h2.mvstore.FileStore.compactRewrite(FileStore.java:1898)
at org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1857)
at org.h2.mvstore.RandomAccessStore.lambda$doHousekeeping$4(RandomAccessStore.java:728)
at org.h2.mvstore.MVStore.tryExecuteUnderStoreLock(MVStore.java:937)
... 3 more

I trace at
org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1906) , at line 1905
C chunk = chunks.get(chunkId);
when get the chunkId from Set set,the map chunks.get is null.
so I trace back,found the set is from
org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1854)
Iterable<C> old = findOldChunks(writeLimit, targetFillRate);
then at line 1857
return !idSet.isEmpty() && compactRewrite(idSet) > 0;
the method compactRewrite excute follow order (line 1894 to 1996)
acceptChunkOccupancyChanges(getTimeSinceCreation(), mvStore.getCurrentVersion()); int rewrittenPageCount = rewriteChunks(set, false);
I notice , the acceptChunkOccupancyChanges (line 1543 start) has an call registerDeadChunk at line 1560.
which will put some chunk to map deadChunks.
and at method dropUnusedChunks (line 645) will remove the chunk at deadChunks.

the method dropUnusedChunks will be called at MVStore.store() at MVStore.java (line 807).and the MVStore.store() will be called at mvstore.commit() or mvstore.tryCommit().

So,I suppose the follow order will cause the exception
doHousekeeping excute
Iterable<C> old = findOldChunks(writeLimit, targetFillRate);``acceptChunkOccupancyChanges(getTimeSinceCreation(), mvStore.getCurrentVersion());
then some chunk in old set also in deadChunks ,let's mark it A chunk
then my application commit or try commit at this time,cause the dropUnusedChunks drop A in deadChunks,so chunks.remove(A).
doHousekeeping thread excute follow method
int rewrittenPageCount = rewriteChunks(set, false);
then chunks.get(A) will return null chunk object at line 1905
then the NullPointerException throw at FileStore.getToC()
I also notice rewriteChunks at FileStore.java line 1848 has a lock serializationLock
but I not found serializationLock at mvstore.commit() or mvstore.tryCommit().
so the order I suppose will happed,right?

`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions