mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
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.
FossilOrigin-Name: 6341ab2ffef298ca16b323358afbea4a4c1fb0e1
This commit is contained in:
15
manifest
15
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Minor\sstyle\stweaks\sin\sthe\sMSVC\smakefile.
|
C Disable\sthe\sPagerDontWrite()\soptimization\sfor\stemp\stables.\sIt\scan\scause\sdatabase\scorruption\sif\sa\spage\spassed\sto\sPagerDontWrite()\sis\sdirty\sat\sthe\sstart\sof\sa\stransaction\sthat\sis\ssubsequently\srolled\sback.
|
||||||
D 2016-05-03T19:40:54.328
|
D 2016-05-04T11:28:03.301
|
||||||
F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
|
F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc db82b35aef27f412fef14d8534afc022138bcdfd
|
F Makefile.msc db82b35aef27f412fef14d8534afc022138bcdfd
|
||||||
@@ -364,7 +364,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
|||||||
F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
|
F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
|
||||||
F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
|
F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
|
||||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||||
F src/pager.c a8d30c49c231e9a20d05257613db922532588963
|
F src/pager.c c512873311087cd22372f2b076fc869e090e8e16
|
||||||
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
|
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
|
||||||
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
|
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
|
||||||
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
|
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
|
||||||
@@ -1111,6 +1111,7 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
|||||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||||
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
|
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
|
||||||
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
|
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
|
||||||
|
F test/tempdb2.test 4fc92055f2a3f7626c0f2eabbb637dc021b311d5
|
||||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||||
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
||||||
@@ -1486,7 +1487,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P bcaa650e8796984b275eceba0ed477f360295d01
|
P 1b43358f8979c4f18519e824e0d5f6ef2250107c
|
||||||
R 962b079d2f6aa84ad32617180232ff75
|
R ddb8134dc049c780758987466a2a1e86
|
||||||
U mistachkin
|
U dan
|
||||||
Z 45ce4bc83f501da24480cd14c4b0de07
|
Z 527ddc60688e8fba4830106202c052a2
|
||||||
|
@@ -1 +1 @@
|
|||||||
1b43358f8979c4f18519e824e0d5f6ef2250107c
|
6341ab2ffef298ca16b323358afbea4a4c1fb0e1
|
@@ -6008,10 +6008,16 @@ int sqlite3PagerIswriteable(DbPage *pPg){
|
|||||||
**
|
**
|
||||||
** Tests show that this optimization can quadruple the speed of large
|
** Tests show that this optimization can quadruple the speed of large
|
||||||
** DELETE operations.
|
** 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){
|
void sqlite3PagerDontWrite(PgHdr *pPg){
|
||||||
Pager *pPager = pPg->pPager;
|
Pager *pPager = pPg->pPager;
|
||||||
if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
|
if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
|
||||||
PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
|
PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
|
||||||
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
|
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
|
||||||
pPg->flags |= PGHDR_DONT_WRITE;
|
pPg->flags |= PGHDR_DONT_WRITE;
|
||||||
|
77
test/tempdb2.test
Normal file
77
test/tempdb2.test
Normal file
@@ -0,0 +1,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
|
||||||
|
|
Reference in New Issue
Block a user