mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
When possible, avoid taking wal file read-lock 0 in sqlite3_snapshot_get().
FossilOrigin-Name: 34b6ac3d76dbc6819778ec2a0f81cbcdcc0cd1a6303381d97f1c479e4ecdd132
This commit is contained in:
@ -4963,7 +4963,11 @@ int sqlite3_snapshot_get(
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
i64 dummy = 0;
|
||||
sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
sqlite3PagerSnapshotOpen(pPager, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
|
||||
}
|
||||
|
18
src/wal.c
18
src/wal.c
@ -541,6 +541,7 @@ struct Wal {
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
|
||||
int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
sqlite3 *db;
|
||||
@ -3097,7 +3098,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
|
||||
SEH_INJECT_FAULT;
|
||||
if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
|
||||
&& ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
|
||||
#endif
|
||||
){
|
||||
/* The WAL has been completely backfilled (or it is empty).
|
||||
@ -4497,7 +4498,20 @@ void sqlite3WalSnapshotOpen(
|
||||
Wal *pWal,
|
||||
sqlite3_snapshot *pSnapshot
|
||||
){
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
|
||||
/* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In
|
||||
** this case set the bGetSnapshot flag so that if the call to
|
||||
** sqlite3_snapshot_get() is about to read transaction on this wal
|
||||
** file, it does not take read-lock 0 if the wal file has been completely
|
||||
** checkpointed. Taking read-lock 0 would work, but then it would be
|
||||
** possible for a subsequent writer to destroy the snapshot even while
|
||||
** this connection is holding its read-transaction open. This is contrary
|
||||
** to user expectations, so we avoid it by not taking read-lock 0. */
|
||||
pWal->bGetSnapshot = 1;
|
||||
}else{
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
pWal->bGetSnapshot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user