From ff13c7d6a328ceded852d6b25b0ae113ee62eea9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 Jun 2004 21:01:11 +0000 Subject: [PATCH] If a commit fails due to lock contention right after the COMMIT command, take the database back out of autocommit mode. Do not rollback. This gives the user the chance to try the COMMIT again. (CVS 1551) FossilOrigin-Name: 39b4ba95c4a16b28b5e8c7a3331e09cb5796e258 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/vdbe.c | 3 ++- src/vdbeInt.h | 3 ++- src/vdbeaux.c | 15 +++++++++++++-- test/attach2.test | 38 ++++++++++++++++++++++++++------------ 6 files changed, 53 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index b965ba5329..9cae88dd23 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Turn\son\sthe\satomic\smultifile\scommit\slogic.\s\sIt\sdoes\snot\swork\sright\syet,\sbut\nit\shas\sat\sleast\sstopped\sfailing\sasserts.\s(CVS\s1550) -D 2004-06-09T20:03:09 +C If\sa\scommit\sfails\sdue\sto\slock\scontention\sright\safter\sthe\sCOMMIT\scommand,\stake\nthe\sdatabase\sback\sout\sof\sautocommit\smode.\s\sDo\snot\srollback.\s\sThis\sgives\sthe\nuser\sthe\schance\sto\stry\sthe\sCOMMIT\sagain.\s(CVS\s1551) +D 2004-06-09T21:01:11 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -70,16 +70,16 @@ F src/update.c 259f06e7b22c684b2d3dda54a18185892d6e9573 F src/utf.c c2c8e445bfea724f3502609d6389fe66651f02ab F src/util.c e8629f04d920ae968fced709dc7a3a2c62b65ac4 F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f -F src/vdbe.c 5896c7462adcb0a62255f4172d5809dc1b220949 +F src/vdbe.c 90e0e6bdbdf9b77c66f2500374b5784d30c323fa F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde -F src/vdbeInt.h ab592f23ed5a1913f9a506bd7b76c5e39377942a +F src/vdbeInt.h d41605853332bdbd600d7ecd60e1f54bbaea174e F src/vdbeapi.c 4ac95766b0515538037a7aec172ed26142f97cf9 -F src/vdbeaux.c 6412cbc491a51950eb6910647656929ea6aaeccc +F src/vdbeaux.c ca11b43529a6cd7c5c848d1a0562cca15f1e7308 F src/vdbemem.c 04502b81039f9a2b1c9a096e894eecf6d4877508 F src/where.c 32578882a245f8ac3303c5cea4664cd51fc73891 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test aed659e52635662bcd5069599aaca823533edf5a -F test/attach2.test 228eaca954ddb850c35fba7bdc39aac2ab0c80c0 +F test/attach2.test 01f55202c7984f9835b9195a5bff4b5c5f0316ee F test/attach3.test 8259ab833b5dcdf4acd75d9653f42f703ce2e013 F test/auth.test 95809b8f6a9bec18b94d28cafd03fe27d2f8a9e9 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81 @@ -218,7 +218,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P a12bef4a0877fb1dca531509a1186e092727b6d8 -R 701fea12013c3300eecc0127ba6ceafd +P 3674b25edc37145b2b1275dd20580015ace66aa7 +R 54a930519b492184ca6ff8c96e1ccf57 U drh -Z 742136040c4805983d993b10276e9a39 +Z 2cb6cb629daca008ee4d5e7a60ffe6e8 diff --git a/manifest.uuid b/manifest.uuid index 512ae0f9fd..0085621a1e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3674b25edc37145b2b1275dd20580015ace66aa7 \ No newline at end of file +39b4ba95c4a16b28b5e8c7a3331e09cb5796e258 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index c1707f3371..59add81c80 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.362 2004/06/09 20:03:10 drh Exp $ +** $Id: vdbe.c,v 1.363 2004/06/09 21:01:11 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2278,6 +2278,7 @@ case OP_AutoCommit: { if( i!=db->autoCommit ){ db->autoCommit = i; + p->autoCommitOn |= i; if( pOp->p2 ){ sqlite3RollbackAll(db); } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 9512d42313..5cc05d47cb 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -323,10 +323,11 @@ struct Vdbe { int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ - u8 resOnStack; /* True if there are result values on the stack */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ + u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ + u8 autoCommitOn; /* True if autocommit got turned on by this program */ }; /* diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 0486aca9c9..f16a990128 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -971,7 +971,7 @@ static int vdbeCommit(sqlite *db){ u32 random; sqliteFree(zMaster); sqlite3Randomness(sizeof(random), &random); - zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random); + zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff); if( !zMaster ){ return SQLITE_NOMEM; } @@ -1134,7 +1134,18 @@ int sqlite3VdbeReset(Vdbe *p, char **pzErrMsg){ p->rc = vdbeCommit(db); if( p->rc!=SQLITE_OK ){ sqlite3Error(p->db, p->rc, 0); - xFunc = sqlite3BtreeRollback; + if( p->rc==SQLITE_BUSY && p->autoCommitOn ){ + /* If we just now have turned autocommit on (meaning we just have + ** finished executing a COMMIT command) but the commit fails due + ** to lock contention, autocommit back off. This gives the user + ** the opportunity to try again after the lock that was preventing + ** the commit has cleared. */ + db->autoCommit = 0; + }else{ + /* If the command just executed was not a COMMIT command, then + ** rollback whatever the results of that command were */ + xFunc = sqlite3BtreeRollback; + } } }else{ xFunc = sqlite3BtreeRollback; diff --git a/test/attach2.test b/test/attach2.test index a8f5100da4..2008dbbc60 100644 --- a/test/attach2.test +++ b/test/attach2.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach2.test,v 1.14 2004/06/09 17:37:29 drh Exp $ +# $Id: attach2.test,v 1.15 2004/06/09 21:01:12 drh Exp $ # set testdir [file dirname $argv0] @@ -263,27 +263,41 @@ do_test attach2-4.9 { lock_status 4.9.1 db {main shared temp reserved file2 shared} lock_status 4.9.2 db2 {main reserved temp reserved file2 reserved} +set sqlite_os_trace 0 +btree_breakpoint do_test attach2-4.10 { - # Release the locks held by handle 'db2' - execsql {COMMIT} db2 -} {} + # We cannot commit db2 while db is holding a read-lock + catchsql {COMMIT} db2 +} {1 {database is locked}} lock_status 4.10.1 db {main shared temp reserved file2 shared} -lock_status 4.10.2 db2 {main unlocked temp unlocked file2 unlocked} +lock_status 4.10.2 db2 {main reserved temp reserved file2 reserved} do_test attach2-4.11 { + # db is able to commit. + catchsql {COMMIT} +} {0 {}} + +lock_status 4.11.1 db {main unlocked temp unlocked file2 unlocked} +lock_status 4.11.2 db2 {main reserved temp reserved file2 reserved} + +do_test attach2-4.12 { + # Now we can commit db2 + catchsql {COMMIT} db2 +} {0 {}} + +lock_status 4.12.1 db {main unlocked temp unlocked file2 unlocked} +lock_status 4.12.2 db2 {main unlocked temp unlocked file2 unlocked} + +do_test attach2-4.13 { execsql {SELECT * FROM file2.t1} } {1 2} -do_test attach2-4.12 { +do_test attach2-4.14 { execsql {INSERT INTO t1 VALUES(1, 2)} } {} -do_test attach2-4.13 { - # Release the locks held by handle 'db' - execsql {ROLLBACK} -} {} -do_test attach2-4.14 { +do_test attach2-4.15 { execsql {SELECT * FROM t1} db2 -} {} +} {1 2 1 2} db close db2 close