Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Disable the PagerDontWrite() optimization for temp tables. It can cause database corruption if a page passed to PagerDontWrite() is dirty at the start of a transaction that is subsequently rolled back. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6341ab2ffef298ca16b323358afbea4a |
User & Date: | dan 2016-05-04 11:28:03.301 |
Context
2016-05-04
| ||
14:20 | Portability enhancements to the configure script on the amalgamation tarball. (check-in: 7184c4b886 user: drh tags: trunk) | |
11:28 | Disable the PagerDontWrite() optimization for temp tables. It can cause database corruption if a page passed to PagerDontWrite() is dirty at the start of a transaction that is subsequently rolled back. (check-in: 6341ab2ffe user: dan tags: trunk) | |
2016-05-03
| ||
19:40 | Minor style tweaks in the MSVC makefile. (check-in: 1b43358f89 user: mistachkin tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 | ** ** The overlying software layer calls this routine when all of the data ** on the given page is unused. The pager marks the page as clean so ** that it does not get written to disk. ** ** Tests show that this optimization can quadruple the speed of large ** DELETE operations. */ void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; | > > > > > > | | 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 | ** ** The overlying software layer calls this routine when all of the data ** on the given page is unused. The pager marks the page as clean so ** that it does not get written to disk. ** ** Tests show that this optimization can quadruple the speed of large ** DELETE operations. ** ** This optimization cannot be used with a temp-file, as the page may ** have been dirty at the start of the transaction. In that case, if ** memory pressure forces page pPg out of the cache, the data does need ** to be written out to disk so that it may be read back in if the ** current transaction is rolled back. */ void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) pPg->flags |= PGHDR_DONT_WRITE; pPg->flags &= ~PGHDR_WRITEABLE; pager_set_pagehash(pPg); } } |
︙ | ︙ |
Added test/tempdb2.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 | # 2016 March 3 # # 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. # #*********************************************************************** set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tempdb2 db close sqlite3 db "" proc int2str {i} { string range [string repeat "$i." 450] 0 899 } db func int2str int2str #------------------------------------------------------------------------- # # 1.1: Write a big transaction to the db. One so large that it forces # the file to be created and the cache flushed to disk on COMMIT. # # 1.2: Write a small transaction - one small enough that it remains in # memory on COMMIT. All the pages of table [t1] are now dirty. # # 1.3: Delete the contents of [t1]. This moves all of its leaves to the # free-list and causes the btree layer to call PagerDontWrite() on # each of them. # # Then do a big update on table [t2]. So big that the former leaves # of [t1] are forced out of the cache. Then roll back the transaction. # If the PagerDontWrite() calls are honoured and the data is not written # to disk, the update made in test 1.2 will be lost at this point. Or, if # they are ignored (as they should be for temp databases), the update # will be safely written out to disk before the cache entries are # discarded. # do_execsql_test 1.1 { PRAGMA page_size=1024; PRAGMA cache_size=50; BEGIN; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, int2str(1)); INSERT INTO t1 VALUES(2, int2str(1)); INSERT INTO t1 VALUES(3, int2str(1)); CREATE TABLE t2(a INTEGER PRIMARY KEY, b); WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 ) INSERT INTO t2 SELECT x, int2str(x) FROM c; COMMIT; PRAGMA lock_status; } {main unlocked temp closed} do_execsql_test 1.2 { UPDATE t1 SET b=int2str(2); SELECT b=int2str(2) FROM t1 } {1 1 1} do_execsql_test 1.3 { BEGIN; DELETE FROM t1; UPDATE t2 SET b=int2str(a+1); ROLLBACK; } do_execsql_test 1.4 { SELECT b=int2str(2) FROM t1 } {1 1 1} finish_test |