Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Require exclusive access to the db to wrap the wal file. Have "PRAGMA wal_checkpoint = restart" block for this. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | server-edition |
Files: | files | file ages | folders |
SHA3-256: |
cbf44ed9758d577e1450b53e645b73c9 |
User & Date: | dan 2017-05-12 18:52:27.743 |
Context
2017-05-13
| ||
19:07 | Avoid running recovery while there is another read/write client. (check-in: a38858a24c user: dan tags: server-edition) | |
2017-05-12
| ||
18:52 | Require exclusive access to the db to wrap the wal file. Have "PRAGMA wal_checkpoint = restart" block for this. (check-in: cbf44ed975 user: dan tags: server-edition) | |
2017-05-10
| ||
16:18 | Fix a problem causing a lock to be held past the end of a transaction. Use a blocking lock to take the read-lock on page 1 taken by all transactions. (check-in: 2584df3d42 user: dan tags: server-edition) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 | ** checkpointed and behave accordingly. This seems unsafe though, ** as it would leave the system in a state where the contents of ** the wal-index header do not match the contents of the ** file-system. To avoid this, update the wal-index header to ** indicate that the log file contains zero valid frames. */ walRestartHdr(pWal, salt1); rc = sqlite3OsTruncate(pWal->pWalFd, 0); } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); } } } walcheckpoint_out: | > > > | 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | ** checkpointed and behave accordingly. This seems unsafe though, ** as it would leave the system in a state where the contents of ** the wal-index header do not match the contents of the ** file-system. To avoid this, update the wal-index header to ** indicate that the log file contains zero valid frames. */ walRestartHdr(pWal, salt1); rc = sqlite3OsTruncate(pWal->pWalFd, 0); }else if( walIsServer(pWal) ){ assert( eMode==SQLITE_CHECKPOINT_RESTART ); walRestartHdr(pWal, salt1); } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); } } } walcheckpoint_out: |
︙ | ︙ | |||
3122 3123 3124 3125 3126 3127 3128 | if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){ iFirst = pLive->mxFrame+1; } /* See if it is possible to write these frames into the start of the ** log file, instead of appending to it at pWal->hdr.mxFrame. */ | | | 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 | if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){ iFirst = pLive->mxFrame+1; } /* See if it is possible to write these frames into the start of the ** log file, instead of appending to it at pWal->hdr.mxFrame. */ if( walIsServer(pWal)==0 && SQLITE_OK!=(rc = walRestartLog(pWal)) ){ return rc; } /* If this is the first frame written into the log, write the WAL ** header to the start of the WAL file. See comments at the top of ** this source file for a description of the WAL header format. */ |
︙ | ︙ | |||
3375 3376 3377 3378 3379 3380 3381 | ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained ** immediately, and a busy-handler is configured, it is invoked and the ** writer lock retried until either the busy-handler returns 0 or the ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ if( walIsServer(pWal) ){ | > > > > > | > | 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 | ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained ** immediately, and a busy-handler is configured, it is invoked and the ** writer lock retried until either the busy-handler returns 0 or the ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ if( walIsServer(pWal) ){ if( eMode>=SQLITE_CHECKPOINT_RESTART ){ /* Exclusive lock on page 1. This is exclusive access to the db. */ rc = sqlite3ServerLock(pWal->pServer, 1, 1, 1); }else{ /* Take the server write-lock ("page" 0) */ rc = sqlite3ServerLock(pWal->pServer, 0, 1, 1); } }else{ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); } if( rc==SQLITE_OK ){ pWal->writeLock = 1; }else if( rc==SQLITE_BUSY ){ eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
︙ | ︙ | |||
3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 | } /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } /* Return the value to pass to a sqlite3_wal_hook callback, the ** number of frames in the WAL at the point of the last commit since ** sqlite3WalCallback() was called. If no commits have occurred since ** the last call, then return 0. | > | 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 | } /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); if( walIsServer(pWal) ) sqlite3ServerEnd(pWal->pServer); return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } /* Return the value to pass to a sqlite3_wal_hook callback, the ** number of frames in the WAL at the point of the last commit since ** sqlite3WalCallback() was called. If no commits have occurred since ** the last call, then return 0. |
︙ | ︙ |
Changes to test/serverwal.test.
︙ | ︙ | |||
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 | } db2 } {} do_test 2.2 { execsql COMMIT db execsql COMMIT db2 } {} db close #------------------------------------------------------------------------- # That the wal file can be wrapped around. # reset_db do_execsql_test 3.0 { PRAGMA journal_mode = wal; CREATE TABLE ttt(a, b); INSERT INTO ttt VALUES(1, 2); INSERT INTO ttt VALUES(3, 4); INSERT INTO ttt VALUES(5, 6); INSERT INTO ttt VALUES(7, 8); INSERT INTO ttt VALUES(9, 10); } {wal} do_test 3.1 { set N [file size test.db-wal] execsql { | > | | 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 | } db2 } {} do_test 2.2 { execsql COMMIT db execsql COMMIT db2 } {} db close db2 close #------------------------------------------------------------------------- # That the wal file can be wrapped around. # reset_db do_execsql_test 3.0 { PRAGMA journal_mode = wal; CREATE TABLE ttt(a, b); INSERT INTO ttt VALUES(1, 2); INSERT INTO ttt VALUES(3, 4); INSERT INTO ttt VALUES(5, 6); INSERT INTO ttt VALUES(7, 8); INSERT INTO ttt VALUES(9, 10); } {wal} do_test 3.1 { set N [file size test.db-wal] execsql { PRAGMA wal_checkpoint = restart; INSERT INTO ttt VALUES(11, 12); INSERT INTO ttt VALUES(13, 14); } expr {$N == [file size test.db-wal]} } {1} #------------------------------------------------------------------------- |
︙ | ︙ | |||
105 106 107 108 109 110 111 112 113 | PRAGMA integrity_check; BEGIN; UPDATE ttt SET b=a; ROLLBACK; PRAGMA integrity_check; } {ok ok} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | PRAGMA integrity_check; BEGIN; UPDATE ttt SET b=a; ROLLBACK; PRAGMA integrity_check; } {ok ok} reset_db do_execsql_test 5.1 { CREATE TABLE xyz(a); PRAGMA journal_mode = wal; INSERT INTO xyz VALUES(1); INSERT INTO xyz VALUES(2); INSERT INTO xyz VALUES(3); } {wal} breakpoint do_test 5.2 { sqlite3 db2 test.db execsql { SELECT * FROM xyz } db2 } {1 2 3} do_execsql_test 5.3 { PRAGMA wal_checkpoint = restart } {0 0 0} do_test 5.4 { execsql { SELECT * FROM xyz } db2 } {1 2 3} finish_test |