Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -8173,16 +8173,22 @@ oldCell = findCell(pPage, idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } rc = clearCell(pPage, oldCell, &info); - if( info.nSize==szNew && info.nLocal==info.nPayload ){ + if( info.nSize==szNew && info.nLocal==info.nPayload + && (!ISAUTOVACUUM || szNewminLocal) + ){ /* Overwrite the old cell with the new if they are the same size. ** We could also try to do this if the old cell is smaller, then add ** the leftover space to the free list. But experiments show that ** doing that is no faster then skipping this optimization and just - ** calling dropCell() and insertCell(). */ + ** calling dropCell() and insertCell(). + ** + ** This optimization cannot be used on an autovacuum database if the + ** new entry uses overflow pages, as the insertCell() call below is + ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; memcpy(oldCell, newCell, szNew); return SQLITE_OK; } Index: test/autovacuum.test ================================================================== --- test/autovacuum.test +++ test/autovacuum.test @@ -703,7 +703,14 @@ do_test autovacuum-9.5 { execsql { DELETE FROM t1 WHERE rowid > (SELECT max(a)/2 FROM t1) } file size test.db } $::sqlite_pending_byte +do_execsql_test autovacuum-10.1 { + DROP TABLE t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + INSERT INTO t1 VALUES(25, randomblob(104)); + REPLACE INTO t1 VALUES(25, randomblob(1117)); + PRAGMA integrity_check; +} {ok} finish_test