Safe truncate (#2218)

* Move relation sie cache to layered timeline

* Fix obtaining current LSN for relation size cache

* Resolve merge conflicts

* Resolve merge conflicts

* Reestore 'lsn' field in DatadirModification

* adjust DatadirModification lsn in ingest_record

* Fix formatting

* Pass lsn to get_relsize

* Fix merge conflict

* Update pageserver/src/pgdatadir_mapping.rs

Co-authored-by: Heikki Linnakangas <heikki@zenith.tech>

* Update pageserver/src/pgdatadir_mapping.rs

Co-authored-by: Heikki Linnakangas <heikki@zenith.tech>

* Check if relation exists before trying to truncat it

refer #1932

* Add test reporducing FSM truncate problem

Co-authored-by: Heikki Linnakangas <heikki@zenith.tech>
This commit is contained in:
Konstantin Knizhnik
2022-08-09 22:45:33 +03:00
committed by GitHub
parent 1fc761983f
commit 4227cfc96e
3 changed files with 27 additions and 11 deletions

View File

@@ -708,20 +708,25 @@ impl<'a, T: DatadirTimeline> DatadirModification<'a, T> {
/// Truncate relation /// Truncate relation
pub fn put_rel_truncation(&mut self, rel: RelTag, nblocks: BlockNumber) -> Result<()> { pub fn put_rel_truncation(&mut self, rel: RelTag, nblocks: BlockNumber) -> Result<()> {
ensure!(rel.relnode != 0, "invalid relnode"); ensure!(rel.relnode != 0, "invalid relnode");
let size_key = rel_size_to_key(rel); let last_lsn = self.tline.get_last_record_lsn();
if self.tline.get_rel_exists(rel, last_lsn)? {
let size_key = rel_size_to_key(rel);
// Fetch the old size first
let old_size = self.get(size_key)?.get_u32_le();
// Fetch the old size first // Update the entry with the new size.
let old_size = self.get(size_key)?.get_u32_le(); let buf = nblocks.to_le_bytes();
self.put(size_key, Value::Image(Bytes::from(buf.to_vec())));
// Update the entry with the new size. // Update relation size cache
let buf = nblocks.to_le_bytes(); self.tline.set_cached_rel_size(rel, self.lsn, nblocks);
self.put(size_key, Value::Image(Bytes::from(buf.to_vec())));
// Update relation size cache // Update relation size cache
self.tline.set_cached_rel_size(rel, self.lsn, nblocks); self.tline.set_cached_rel_size(rel, self.lsn, nblocks);
// Update logical database size. // Update logical database size.
self.pending_nblocks -= old_size as isize - nblocks as isize; self.pending_nblocks -= old_size as isize - nblocks as isize;
}
Ok(()) Ok(())
} }

View File

@@ -0,0 +1,11 @@
from fixtures.log_helper import log
from fixtures.neon_fixtures import NeonEnv, NeonEnvBuilder, NeonPageserverHttpClient
import pytest
def test_fsm_truncate(neon_env_builder: NeonEnvBuilder):
env = neon_env_builder.init_start()
env.neon_cli.create_branch("test_fsm_truncate")
pg = env.postgres.create_start('test_fsm_truncate')
pg.safe_psql(
'CREATE TABLE t1(key int); CREATE TABLE t2(key int); TRUNCATE TABLE t1; TRUNCATE TABLE t2;')