SQLite

Check-in [b81a31495b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Lock the wal file for all snapshot transactions, even if they would not otherwise require this, preventing checkpointers and writers from wrapping the wal file. This means that if one connection has an open snapshot transaction it is guaranteed that a second connection can open a transaction on the same snapshot.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: b81a31495bd27c1d96f7df653da3502054240cb5acf66b860da7f0f9b422a524
User & Date: dan 2017-11-28 13:39:41.135
Context
2017-11-28
20:43
Fix an assertion fault found by OSSFuzz. (check-in: 75d699877f user: dan tags: trunk)
13:48
Merge the snapshots-always-lock-the-wal-file change into this branch. (check-in: 3ec976e015 user: dan tags: apple-osx)
13:39
Lock the wal file for all snapshot transactions, even if they would not otherwise require this, preventing checkpointers and writers from wrapping the wal file. This means that if one connection has an open snapshot transaction it is guaranteed that a second connection can open a transaction on the same snapshot. (check-in: b81a31495b user: dan tags: trunk)
07:52
Add experimental feature to detect threading bugs in apps that use SQLITE_CONFIG_MULTITHREADED. Enabled at compile time using SQLITE_ENABLE_MULTITHREADED_CHECKS. (check-in: 40b598c839 user: dan tags: trunk)
2017-09-23
07:46
Experimental change so that snapshot transactions always lock the wal file - preventing writers or truncate-checkpointers from wrapping it. (Closed-Leaf check-in: d71eeaab9e user: dan tags: snapshots-lock-wal)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/wal.c.
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
  }

  assert( pWal->nWiData>0 );
  assert( pWal->apWiData[0]!=0 );
  pInfo = walCkptInfo(pWal);
  if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
   && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0
     || 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr)))
#endif
  ){
    /* The WAL has been completely backfilled (or it is empty).
    ** and can be safely ignored.
    */
    rc = walLockShared(pWal, WAL_READ_LOCK(0));
    walShmBarrier(pWal);







|
<







2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
  }

  assert( pWal->nWiData>0 );
  assert( pWal->apWiData[0]!=0 );
  pInfo = walCkptInfo(pWal);
  if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
   && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)

#endif
  ){
    /* The WAL has been completely backfilled (or it is empty).
    ** and can be safely ignored.
    */
    rc = walLockShared(pWal, WAL_READ_LOCK(0));
    walShmBarrier(pWal);
Added test/snapshot3.test.








































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 2016 September 23
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of this file is the sqlite3_snapshot_xxx() APIs.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !snapshot {finish_test; return}
set testprefix snapshot3

# This test does not work with the inmemory_journal permutation. The reason
# is that each connection opened as part of this permutation executes
# "PRAGMA journal_mode=memory", which fails if the database is in wal mode
# and there are one or more existing connections.
if {[permutation]=="inmemory_journal"} {
  finish_test
  return
}

#-------------------------------------------------------------------------
# This block of tests verifies that it is not possible to wrap the wal
# file - using a writer or a "PRAGMA wal_checkpoint = TRUNCATE" - while
# there is an open snapshot transaction (transaction opened using
# sqlite3_snapshot_open()).
#
do_execsql_test 1.0 {
  CREATE TABLE t1(y);
  PRAGMA journal_mode = wal;
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 VALUES(2);
  INSERT INTO t1 VALUES(3);
  INSERT INTO t1 VALUES(4);
} {wal}

do_test 1.1 {
  sqlite3 db2 test.db
  sqlite3 db3 test.db

  execsql {SELECT * FROM sqlite_master} db2
  execsql {SELECT * FROM sqlite_master} db3

  db2 trans { set snap [sqlite3_snapshot_get_blob db2 main] }
  db2 eval { SELECT * FROM t1 }
} {1 2 3 4}

do_test 1.2 {
  execsql BEGIN db2
  sqlite3_snapshot_open_blob db2 main $snap
  db2 eval { SELECT * FROM t1 }
} {1 2 3 4}

do_test 1.2 {
  execsql END db2
  execsql { PRAGMA wal_checkpoint }

  execsql BEGIN db2
  sqlite3_snapshot_open_blob db2 main $snap
  db2 eval { SELECT * FROM t1 }
} {1 2 3 4}

set sz [file size test.db-wal]
do_test 1.3 {
  execsql { PRAGMA wal_checkpoint = truncate }
  file size test.db-wal
} $sz

do_test 1.4 {
  execsql BEGIN db3
  list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg
} {0 {}}

do_test 1.5 {
  db3 eval { SELECT * FROM t1; END }
} {1 2 3 4}

do_test 1.6 {
  db2 eval { SELECT * FROM t1; END }
} {1 2 3 4}

do_test 1.7 {
  execsql { PRAGMA wal_checkpoint = truncate }
  file size test.db-wal
} 0

do_test 1.8 {
  execsql BEGIN db3
  list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg
} {1 SQLITE_BUSY_SNAPSHOT}

finish_test