Skip to content

Commit a907a2a

Browse files
committed
PG-1842 PG-1843 Optimize deletion of leftover relation keys
Instead of first deleteing any leftover key and then writing the new key we do a single pass through the file where we replace any old key that we find. To make this happen on redo too we need to stop generating a separate WAL record for the key deletion for encrypted tables and only generate that record for unecrypted tables where we still need a key deleteion record. We except this optimization to primarily be visible on WAL replay where only a single backend is used to replay everything, but it also speeds up table creation in general on workloads with many tables.
1 parent 13c1038 commit a907a2a

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static void pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off
9797
static int pg_tde_file_header_write(const char *tde_filename, int fd, const TDESignedPrincipalKeyInfo *signed_key_info, off_t *bytes_written);
9898
static void pg_tde_initialize_map_entry(TDEMapEntry *map_entry, const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, const InternalKey *rel_key_data);
9999
static int pg_tde_open_file_write(const char *tde_filename, const TDESignedPrincipalKeyInfo *signed_key_info, bool truncate, off_t *curr_pos);
100-
static void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, const TDEPrincipalKey *principal_key);
100+
static void pg_tde_replace_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, const TDEPrincipalKey *principal_key);
101101

102102
void
103103
pg_tde_save_smgr_key(RelFileLocator rel, const InternalKey *rel_key_data)
@@ -114,7 +114,7 @@ pg_tde_save_smgr_key(RelFileLocator rel, const InternalKey *rel_key_data)
114114
errhint("Use pg_tde_set_key_using_database_key_provider() or pg_tde_set_key_using_global_key_provider() to configure one."));
115115
}
116116

117-
pg_tde_write_key_map_entry(&rel, rel_key_data, principal_key);
117+
pg_tde_replace_key_map_entry(&rel, rel_key_data, principal_key);
118118
LWLockRelease(lock_pk);
119119
}
120120

@@ -452,11 +452,12 @@ pg_tde_write_one_map_entry(int fd, const TDEMapEntry *map_entry, off_t *offset,
452452
* concurrent in place updates leading to data conflicts.
453453
*/
454454
void
455-
pg_tde_write_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, const TDEPrincipalKey *principal_key)
455+
pg_tde_replace_key_map_entry(const RelFileLocator *rlocator, const InternalKey *rel_key_data, const TDEPrincipalKey *principal_key)
456456
{
457457
char db_map_path[MAXPGPATH];
458458
int map_fd;
459459
off_t curr_pos = 0;
460+
off_t write_pos = 0;
460461
TDEMapEntry write_map_entry;
461462
TDESignedPrincipalKeyInfo signed_key_Info;
462463

@@ -481,22 +482,26 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, const InternalKey *re
481482

482483
if (!pg_tde_read_one_map_entry(map_fd, &read_map_entry, &curr_pos))
483484
{
484-
curr_pos = prev_pos;
485+
if (write_pos == 0)
486+
write_pos = prev_pos;
485487
break;
486488
}
487489

488-
if (read_map_entry.type == MAP_ENTRY_TYPE_EMPTY)
490+
if (read_map_entry.spcOid == rlocator->spcOid && read_map_entry.relNumber == rlocator->relNumber)
489491
{
490-
curr_pos = prev_pos;
492+
write_pos = prev_pos;
491493
break;
492494
}
495+
496+
if (write_pos == 0 && read_map_entry.type == MAP_ENTRY_TYPE_EMPTY)
497+
write_pos = prev_pos;
493498
}
494499

495500
/* Initialize map entry and encrypt key */
496501
pg_tde_initialize_map_entry(&write_map_entry, principal_key, rlocator, rel_key_data);
497502

498503
/* Write the given entry at curr_pos; i.e. the free entry. */
499-
pg_tde_write_one_map_entry(map_fd, &write_map_entry, &curr_pos, db_map_path);
504+
pg_tde_write_one_map_entry(map_fd, &write_map_entry, &write_pos, db_map_path);
500505

501506
CloseTransientFile(map_fd);
502507
}

contrib/pg_tde/src/smgr/pg_tde_smgr.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ tde_smgr_create_key_redo(const RelFileLocator *rlocator)
113113
{
114114
InternalKey key;
115115

116-
if (pg_tde_has_smgr_key(*rlocator))
117-
return;
118-
119116
pg_tde_generate_internal_key(&key);
120117

121118
pg_tde_save_smgr_key(*rlocator, &key);
@@ -383,18 +380,18 @@ tde_mdcreate(RelFileLocator relold, SMgrRelation reln, ForkNumber forknum, bool
383380
if (forknum != MAIN_FORKNUM)
384381
return;
385382

386-
/*
387-
* If we have a key for this relation already, we need to remove it. This
388-
* can happen if OID is re-used after a crash left a key for a
389-
* non-existing relation in the key file.
390-
*
391-
* If we're in redo, a separate WAL record will make sure the key is
392-
* removed.
393-
*/
394-
tde_smgr_delete_leftover_key(&reln->smgr_rlocator);
395-
396383
if (!tde_smgr_should_encrypt(&reln->smgr_rlocator, &relold))
397384
{
385+
/*
386+
* If we have a key for this relation already, we need to remove it.
387+
* This can happen if OID is re-used after a crash left a key for a
388+
* non-existing relation in the key file.
389+
*
390+
* Old keys for encrypted tables are replace when creating the new
391+
* key.
392+
*/
393+
tde_smgr_delete_leftover_key(&reln->smgr_rlocator);
394+
398395
tdereln->encryption_status = RELATION_NOT_ENCRYPTED;
399396
return;
400397
}

0 commit comments

Comments
 (0)