From ba726f4939278f8d4f69149614276553a37657cc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Mar 2010 15:48:13 +0000 Subject: [PATCH] Do create, open, or initialize the rollback journal until something actually needs to be written into the journal. That way, expensive filesystem operations are avoided if the transaction ends up being a no-op. FossilOrigin-Name: b78e58ae1570ab4d66a69db445a752c6456038a0 --- manifest | 28 +++++++++++++++++++--------- manifest.uuid | 2 +- src/pager.c | 34 ++++++++++++++++++---------------- test/jrnlmode.test | 6 +++--- test/misc1.test | 8 ++++++-- 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 97fceeb864..dde1ec17ba 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Rewrite\sa\scouple\sof\squeries\sused\sinternally\sby\sFTS3\sto\stake\sadvantage\sof\sthe\s"SELECT\smax(x)\sFROM\s..."\soptimization. -D 2010-03-19T06:59:19 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Do\screate,\sopen,\sor\sinitialize\sthe\srollback\sjournal\suntil\ssomething\sactually\nneeds\sto\sbe\swritten\sinto\sthe\sjournal.\s\sThat\sway,\sexpensive\sfilesystem\noperations\sare\savoided\sif\sthe\stransaction\sends\sup\sbeing\sa\sno-op. +D 2010-03-19T15:48:14 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -152,7 +155,7 @@ F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30 F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f F src/os_unix.c 148d2f625db3727250c0b880481ae7630b6d0eb0 F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053 -F src/pager.c db7a3988cd5958011c3bce4ed1b788c40107628a +F src/pager.c 8e5cefa30e46da6824cb7c6f092b3894b4c3b7bf F src/pager.h ef8a2cf10084f60ab45ee2dfded8bf8b0c655ddf F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c 4956b41d6ba913f7a8a56fbf32be78caed0e45c2 @@ -457,7 +460,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901 F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 -F test/jrnlmode.test a765844f22b3f6d72d78a68d5decd26c64bb859c +F test/jrnlmode.test a7407c0f193696f0ef303c663916c89e3bc4605d F test/jrnlmode2.test fe79ea1f0375c926b8de0362ddf94f34a64135fd F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710 F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05 @@ -507,7 +510,7 @@ F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0 F test/minmax3.test a38686c33b07d595e98a2fc6d3aa84a5e886a972 -F test/misc1.test 1b89c02c4a33b49dee4cd1d20d161aaaba719075 +F test/misc1.test e56baf44656dd68d6475a4b44521045a60241e9b F test/misc2.test a628db7b03e18973e5d446c67696b03de718c9fd F test/misc3.test 72c5dc87a78e7865c5ec7a969fc572913dbe96b6 F test/misc4.test 91e8ed25c092c2bb4e0bb01864631e2930f8d7de @@ -793,7 +796,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 39b34ac4a7bd06144b3630c0ad71bad0615418b6 -R 0beeb22a2bd626a841f0cfea3315c725 -U dan -Z 78efa9b25fddb1d945403b19c00fb61f +P b7e42ae77443b33e0ab83265064830594094dc7c +R dfec378b8748bf5ce92e741ebb2a5676 +U drh +Z f8af9d6e06b574d3c55a4284484dcb07 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFLo5zBoxKgR168RlERAsHsAJ9MbPKPBalfwi46+MveEw5XQfUkFACeJa58 +S6m/QgLe0r+Ynag8entdHnE= +=P1LI +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 3010035a4a..ce25ad01d1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b7e42ae77443b33e0ab83265064830594094dc7c \ No newline at end of file +b78e58ae1570ab4d66a69db445a752c6456038a0 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 0f69518d05..3124e81bd9 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1315,11 +1315,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); #endif - sqlite3PcacheCleanAll(pPager->pPCache); sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; pPager->nRec = 0; } + sqlite3PcacheCleanAll(pPager->pPCache); if( !pPager->exclusiveMode ){ rc2 = osUnlock(pPager->fd, SHARED_LOCK); @@ -4106,12 +4106,11 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ } } - /* If the required locks were successfully obtained, open the journal - ** file and write the first journal-header to it. + /* No need to open the journal file at this time. It will be + ** opened before it is written to. If we defer opening the journal, + ** we might save the work of creating a file if the transaction + ** ends up being a no-op. */ - if( rc==SQLITE_OK && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - rc = pager_open_journal(pPager); - } }else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){ /* This happens when the pager was in exclusive-access mode the last ** time a (read or write) transaction was successfully concluded @@ -4126,7 +4125,6 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ } PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); - assert( !isOpen(pPager->jfd) || pPager->journalOff>0 || rc!=SQLITE_OK ); if( rc!=SQLITE_OK ){ assert( !pPager->dbModified ); /* Ignore any IO error that occurs within pager_end_transaction(). The @@ -4182,11 +4180,11 @@ static int pager_write(PgHdr *pPg){ ** or both. ** ** Higher level routines should have already started a transaction, - ** which means they have acquired the necessary locks and opened - ** a rollback journal. Double-check to makes sure this is the case. + ** which means they have acquired the necessary locks but the rollback + ** journal might not yet be open. */ rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory); - if( NEVER(rc!=SQLITE_OK) ){ + if( rc!=SQLITE_OK ){ return rc; } if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ @@ -4921,11 +4919,6 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ int ii; /* Iterator variable */ PagerSavepoint *aNew; /* New Pager.aSavepoint array */ - /* Either there is no active journal or the sub-journal is open or - ** the journal is always stored in memory */ - assert( pPager->nSavepoint==0 || isOpen(pPager->sjfd) || - pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); - /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM ** if the allocation fails. Otherwise, zero the new portion in case a ** malloc failure occurs while populating it in the for(...) loop below. @@ -4944,7 +4937,7 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ for(ii=nCurrent; iidbSizeValid ); aNew[ii].nOrig = pPager->dbSize; - if( isOpen(pPager->jfd) && ALWAYS(pPager->journalOff>0) ){ + if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ aNew[ii].iOffset = pPager->journalOff; }else{ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); @@ -5337,6 +5330,15 @@ int sqlite3PagerJournalMode(Pager *pPager, int eMode){ if( isOpen(pPager->jfd) ){ sqlite3OsClose(pPager->jfd); } + assert( (PAGER_JOURNALMODE_TRUNCATE & 1)==1 ); + assert( (PAGER_JOURNALMODE_PERSIST & 1)==1 ); + assert( (PAGER_JOURNALMODE_DELETE & 1)==0 ); + assert( (PAGER_JOURNALMODE_MEMORY & 1)==0 ); + assert( (PAGER_JOURNALMODE_OFF & 1)==0 ); + if( (pPager->journalMode & 1)==1 && (eMode & 1)==0 + && !pPager->exclusiveMode ){ + sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + } pPager->journalMode = (u8)eMode; } return (int)pPager->journalMode; diff --git a/test/jrnlmode.test b/test/jrnlmode.test index ea235d34b3..faf83cb70e 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -484,7 +484,7 @@ ifcapable pragma { INSERT INTO t4 VALUES(3, 4); } file exists test.db-journal - } {1} + } {0} do_test jrnlmode-6.7 { execsql { COMMIT; @@ -493,11 +493,11 @@ ifcapable pragma { } {1 2 3 4} do_test jrnlmode-6.8 { file exists test.db-journal - } {1} + } {0} do_test jrnlmode-6.9 { execsql { PRAGMA journal_mode = DELETE; - BEGIN IMMEDIATE; COMMIT; + BEGIN IMMEDIATE; INSERT INTO t4 VALUES(1,2); COMMIT; } file exists test.db-journal } {0} diff --git a/test/misc1.test b/test/misc1.test index 7f93686f0f..a78e4884e9 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -481,8 +481,12 @@ do_test misc1-14.1 { execsql {BEGIN} file exists ./test.db-journal } {0} -do_test misc1-14.2 { - execsql {UPDATE t1 SET a=0 WHERE 0} +do_test misc1-14.2a { + execsql {UPDATE t1 SET a=a||'x' WHERE 0} + file exists ../test.db-journal +} {0} +do_test misc1-14.2b { + execsql {UPDATE t1 SET a=a||'y' WHERE 1} file exists ../test.db-journal } {1} do_test misc1-14.3 {