diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 3751c3c62f51033556bdbcfbc6a26fbb1835cceb..de32a015f6c66fe169a91ab5eb6a7caf89815e17 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -970,6 +970,13 @@ dropdb(const char *dbname, bool missing_ok) */ dropDatabaseDependencies(db_id); + /* + * Drop pages for this database that are in the shared buffer cache. This + * is important to ensure that no remaining backend tries to write out a + * dirty buffer to the dead database later... + */ + DropDatabaseBuffers(db_id); + /* * Tell the stats collector to forget it immediately, too. */ diff --git a/src/test/regress/expected/.gitignore b/src/test/regress/expected/.gitignore index 3a57d185c0860229aa4f83089ea5c36854d16075..8fce98e1c48a34f69a5f6a30907107833314c5ac 100644 --- a/src/test/regress/expected/.gitignore +++ b/src/test/regress/expected/.gitignore @@ -40,3 +40,4 @@ partition_ddl.out autovacuum-template0.out rpt_tpch.out session_reset.out +dropdb_check_shared_buffer_cache.out diff --git a/src/test/regress/greenplum_schedule b/src/test/regress/greenplum_schedule index 3b98495a0f519d293935c97b2967023c1cdb2c59..ff341d05fc94d03c52f9beed31df66c94eae306e 100755 --- a/src/test/regress/greenplum_schedule +++ b/src/test/regress/greenplum_schedule @@ -219,7 +219,7 @@ test: metadata_track test: workfile_mgr_test test: session_reset -test: psql_gp_commands pg_resetxlog +test: psql_gp_commands pg_resetxlog dropdb_check_shared_buffer_cache # Check for shmem leak for instrumentation slots test: instr_in_shmem_verify diff --git a/src/test/regress/input/dropdb_check_shared_buffer_cache.source b/src/test/regress/input/dropdb_check_shared_buffer_cache.source new file mode 100644 index 0000000000000000000000000000000000000000..c1b4a60a93824b420c5008906c6630e5e60ca622 --- /dev/null +++ b/src/test/regress/input/dropdb_check_shared_buffer_cache.source @@ -0,0 +1,31 @@ +-- Test that dropping a database will drop pages in the shared buffer cache. + +CREATE OR REPLACE FUNCTION check_shared_buffer_cache_for_dboid(Oid) RETURNS BOOL +AS '@abs_srcdir@/regress.so', 'check_shared_buffer_cache_for_dboid' +LANGUAGE C; + +-- Create a new database and a table. This should create entries in the shared +-- buffer cache with the database Oid in the entries' buffer tag. +CREATE DATABASE dropdb_check_shared_buffer_cache; +\c dropdb_check_shared_buffer_cache +CREATE TABLE dropdb_check_shared_buffer_cache_table (a int); +\c regression + +-- Store the new database's Oid for later use +-- start_ignore +SELECT oid AS dropdb_check_shared_buffer_cache_dboid + FROM pg_database WHERE datname = 'dropdb_check_shared_buffer_cache'; +-- end_ignore +\gset + +-- We expect 'true' that the shared buffer cache contains pages related to our +-- newly created database. +SELECT check_shared_buffer_cache_for_dboid(:dropdb_check_shared_buffer_cache_dboid); + +-- Now drop our database. This should trigger dropping of pages for this +-- database that are in the shared buffer cache. +DROP DATABASE dropdb_check_shared_buffer_cache; + +-- We expect 'false' that the shared buffer cache contains pages related to our +-- dropped database. +SELECT check_shared_buffer_cache_for_dboid(:dropdb_check_shared_buffer_cache_dboid); diff --git a/src/test/regress/output/dropdb_check_shared_buffer_cache.source b/src/test/regress/output/dropdb_check_shared_buffer_cache.source new file mode 100644 index 0000000000000000000000000000000000000000..8471f9796ec402ee11bd77c3f4d5799ef709b0bf --- /dev/null +++ b/src/test/regress/output/dropdb_check_shared_buffer_cache.source @@ -0,0 +1,40 @@ +-- Test that dropping a database will drop pages in the shared buffer cache. +CREATE OR REPLACE FUNCTION check_shared_buffer_cache_for_dboid(Oid) RETURNS BOOL +AS '@abs_srcdir@/regress.so', 'check_shared_buffer_cache_for_dboid' +LANGUAGE C; +-- Create a new database and a table. This should create entries in the shared +-- buffer cache with the database Oid in the entries' buffer tag. +CREATE DATABASE dropdb_check_shared_buffer_cache; +\c dropdb_check_shared_buffer_cache +CREATE TABLE dropdb_check_shared_buffer_cache_table (a int); +\c regression +-- Store the new database's Oid for later use +-- start_ignore +SELECT oid AS dropdb_check_shared_buffer_cache_dboid + FROM pg_database WHERE datname = 'dropdb_check_shared_buffer_cache'; + dropdb_check_shared_buffer_cache_dboid +---------------------------------------- + +(1 row) + +-- end_ignore +\gset +-- We expect 'true' that the shared buffer cache contains pages related to our +-- newly created database. +SELECT check_shared_buffer_cache_for_dboid(:dropdb_check_shared_buffer_cache_dboid); + check_shared_buffer_cache_for_dboid +------------------------------------- + t +(1 row) + +-- Now drop our database. This should trigger dropping of pages for this +-- database that are in the shared buffer cache. +DROP DATABASE dropdb_check_shared_buffer_cache; +-- We expect 'false' that the shared buffer cache contains pages related to our +-- dropped database. +SELECT check_shared_buffer_cache_for_dboid(:dropdb_check_shared_buffer_cache_dboid); + check_shared_buffer_cache_for_dboid +------------------------------------- + f +(1 row) + diff --git a/src/test/regress/regress_gp.c b/src/test/regress/regress_gp.c index 65534812f8cbdcf2f9d57ed9f80bddedf6a817a3..acd5219259ffc6a0722e417de94e62010ce54644 100644 --- a/src/test/regress/regress_gp.c +++ b/src/test/regress/regress_gp.c @@ -40,6 +40,8 @@ #include "executor/spi.h" #include "port/atomics.h" #include "parser/parse_expr.h" +#include "storage/bufmgr.h" +#include "storage/buf_internals.h" #include "libpq/auth.h" #include "libpq/hba.h" #include "utils/builtins.h" @@ -93,6 +95,9 @@ extern Datum check_auth_time_constraints(PG_FUNCTION_ARGS); extern Datum test_consume_xids(PG_FUNCTION_ARGS); extern Datum gp_execute_on_server(PG_FUNCTION_ARGS); +/* Check shared buffer cache for a database Oid */ +extern Datum check_shared_buffer_cache_for_dboid(PG_FUNCTION_ARGS); + /* Triggers */ typedef struct @@ -2016,3 +2021,26 @@ gp_execute_on_server(PG_FUNCTION_ARGS) else PG_RETURN_BOOL(true); } + +/* + * Check if the shared buffer cache contains any pages that have the specified + * database OID in their buffer tag. Return true if an entry is found, else + * return false. + */ +PG_FUNCTION_INFO_V1(check_shared_buffer_cache_for_dboid); +Datum +check_shared_buffer_cache_for_dboid(PG_FUNCTION_ARGS) +{ + Oid databaseOid = PG_GETARG_OID(0); + int i; + + for (i = 0; i < NBuffers; i++) + { + volatile BufferDesc *bufHdr = &BufferDescriptors[i]; + + if (bufHdr->tag.rnode.dbNode == databaseOid) + PG_RETURN_BOOL(true); + } + + PG_RETURN_BOOL(false); +} diff --git a/src/test/regress/sql/.gitignore b/src/test/regress/sql/.gitignore index e3ecc491ea2b725fb86654b6d7d5d54af7bfa2aa..cc1e716f9490441a6e1d674246b42e67971c8d58 100644 --- a/src/test/regress/sql/.gitignore +++ b/src/test/regress/sql/.gitignore @@ -39,3 +39,4 @@ partition_ddl.sql autovacuum-template0.sql rpt_tpch.sql session_reset.sql +dropdb_check_shared_buffer_cache.sql