Oth*_*eus 12 postgresql backup maintenance read-only-database
PostgreSQL 内置的备份机制并不总是很合适。有时,您希望将应用程序置于静止状态,因为它具有您要在备份 PG 数据的同时进行备份的外部数据。但是将应用程序置于静止状态的唯一方法是“锁定”数据库。PG 缺乏数据库范围或集群范围的锁定机制。将 PG 置于只读状态将是以下解决方案中的一部分:
Oth*_*eus 13
在互联网上其他地方剔除答案后,我设计了一个解决方案。其他答案本身就是不完整的。所以我在这里提出一个答案,希望它能让其他人受益。
default_transaction_read_only
设置设置为true
.完成后,您将(在我的解决方案中):
CHECKPOINT
(我认为这是最安全的,但 apg_xlog_switch()
将适用于非常高负载的服务器)pg_stat_clear_snapshot()
恢复读写状态并不是那么简单。如果现在存在只读连接,您必须终止它们以使新的读写状态生效。但是新的连接可能会在杀死现有连接的同时到达。所以再次,你必须
false
另一种策略是更改应用程序使用的角色的权限。这可能非常混乱并且不太通用。
例如,您不仅必须撤销/重新授权表,还必须撤销/重新授予序列、大对象,可能还有模式本身。此外,当您更改访问权限时,现有连接的行为究竟是什么?可能没有影响,这意味着您还需要终止这些后端。最后,假设应用程序对大多数表具有读写访问权限,但对模式中的其他表没有。您必须确保您的重新授予也不包括这些对象。
另一种可能性是通过查询目录并执行动态查询来锁定所有表。这对我的口味来说似乎很危险。
数据库实例名称是“gitlabhq”,应用程序的用户名是“gitlab”。用你自己的替换它:
psql -Upostgres <<'PAUSE_DB'
-- 1. disable new connections
alter database gitlabhq_production with allow_connections = off;
-- 2. Make DB read-only
alter database gitlabhq set default_transaction_read_only = true;
-- 3. Inobtrusively but safely terminate current connections
DO $X$ BEGIN
-- kill open idle connections, try up to 9x. Last time, kill regardless
FOR i IN 1..10 LOOP
PERFORM pg_terminate_backend(pid) from pg_stat_activity where usename = 'gitlab'
and (i >= 10 OR state in ('idle', 'disabled' ));
PERFORM pg_stat_clear_snapshot();
EXIT WHEN NOT EXISTS ( select pid from pg_stat_activity where usename = 'gitlab' );
RAISE NOTICE 'pg backends still open: sleeping 2 seconds';
PERFORM pg_sleep(2);
PERFORM pg_stat_clear_snapshot();
END LOOP;
-- send notice if still open connections
IF EXISTS ( select pid from pg_stat_activity where usename = 'gitlab' ) THEN
RAISE NOTICE 'Hung backends. Backup might not be 100%% consistent';
END IF;
END;$X$;
-- 4. Allow read-only connections while checkpointing/snapshotting
alter database gitlabhq with allow_connections = on;
CHECKPOINT;
Run Code Online (Sandbox Code Playgroud)
alter database gitlabhq_production with allow_connections = off;
alter database gitlabhq set default_transaction_read_only = false;
SELECT pg_stat_clear_snapshot();
SELECT pg_terminate_backend(pid) from pg_stat_activity where usename = 'gitlab';
alter database gitlabhq with allow_connections = on;
Run Code Online (Sandbox Code Playgroud)
在这最后一步中,您可能会终止长时间运行的只读/SELECT 查询,但根据我的经验,这种长时间运行的查询可能会持续数分钟甚至数小时,为了确保正常运行时间,可以终止这些查询其他所有人。
我认为个人希望将此功能作为官方 PostgreSQL 功能。
如果您不想为 PostgreSQL 扩展编写 C 代码,那么您可以在 PostgreSQL 前面放置一个连接池。像 pgBouncer。
pgBouncer能够暂停内置的应用程序活动。尽管要使其非常有用,您需要直接连接(而不是通过 pgbouncer)并在暂停新连接后取消活动连接。只需select pg_terminate_backend(pid) from pg_stat_activity where pid <> pg_backend_pid()
.
但是,如果您愿意亲自动手,则可以使用 C 扩展名来完成。扩展必须:
加载,shared_preload_libraries
以便它可以注册一个小的静态共享内存段,带有一个布尔标志,如db_is_locked。
注册 aProcessUtility_hook
并ExecutorStart_hook
测试 shmem 中的 is-locked 标志,如果设置,则在WaitLatch
循环中休眠,直到它看到该标志再次被清除。(您可以改用解析器钩子)。
用 C 编写两个 SQL 可调用函数。一个设置标志。另一个清除标志并迭代PGPROC
设置所有用户进程的闩锁,因此他们知道立即唤醒。
可选地编写第三个函数,如果设置了标志,则迭代PGXACT
以查找打开的写入事务并通知它们终止。
所有这些都已经作为BDR 扩展的一部分实施,但它是更大系统的一部分。您很可能将相关部分提取到您自己的扩展中。见bdr_locks.c
,bdr_commandfilter.c
,bdr_executor.c
,bdr.c
,等。
请注意,这不会使 PostgreSQL在磁盘上成为只读- 检查指针将继续运行,bgwriter 将继续运行,归档程序仍将运行,等等。所以让您在没有原子的情况下进行数据库备份是不够的文件系统快照或pg_start_backup()
/ pg_stop_backup()
。但是对于您的用例来说很好,暂停数据库中的应用程序活动。
归档时间: |
|
查看次数: |
18643 次 |
最近记录: |