12-BackAndReBack是哪个品牌或产品?

摘要:BackupAndReply PostgreSQL有三种备份方式: SQL备份 (逻辑备份):即类似dump方式 可靠,简单 慢 备份 -- 备份 -- pgdump备份不会导致用户阻塞 -- pg_dump pg_dumpall pg_d
BackupAndReply PostgreSQL有三种备份方式: SQL备份 (逻辑备份):即类似dump方式 可靠,简单 慢 备份 -- 备份 -- pgdump备份不会导致用户阻塞 -- pg_dump pg_dumpall pg_dump [connection-option] [option...] [dbname] 连接信息,库/用户 [postgres@desktop-f5s26of ~]$ pg_dump postgres > postgres.sql [postgres@desktop-f5s26of ~]$ ls data postgres.sql 恢复 -- 恢复 -- 先删除一些表进行测试 drop table student; \q 推出 psql -d postgres < postgres.sql -- 这时进入,发现表已恢复 物理备份 找到文件的实际存储位置,进行备份。 快 写入时备份可能会丢失数据,不太 稳定。 备份 -- -D 指定备份文件的位置 -Ft 备份文件打包 -Pv 输出详细信息及进度 -U用户 -h ip -p 端口 -R 自动生成配置文件 pg_basebackup -D /pg_basebackup -Ft -Pv -Upostgres -h 192.168.1.13 -p 123456 -R -- 首先创建一个备份目录 mkdir /pg_basebackup -- 设置拥有着 sudo chown -R postgres. /pg_basebackup -- 执行备份 pg_basebackup -D /pg_basebackup -Ft -Pv -Upostgres -h 192.168.1.13 -p 123456 -R ❯ sudo pg_basebackup -D /pg_basebackup -Ft -Pv -Upostgres -h 192.168.1.13 -p 5432 -R -W 口令: pg_basebackup: 开始基础备份,等待检查点完成 pg_basebackup: 已完成检查点 pg_basebackup: 预写日志起始于时间点: 0/CC000028, 基于时间轴1 pg_basebackup: 启动后台 WAL 接收进程 pg_basebackup: 已创建临时复制槽"pg_basebackup_982381" 7754/31628 kB (24%), 0/2 多个表空间 (/pg_basebackup/24585.tar 7754/31628 kB (24%), 1/2 多个表空间 (/pg_basebackup/24585.tar 31640/31640 kB (100%), 1/2 多个表空间 (/pg_basebackup/base.tar 31640/31640 kB (100%), 2/2 多个表空间 pg_basebackup: 预写日志结束点: 0/CC000120 pg_basebackup: 等待后台进程结束流操作... pg_basebackup: 同步数据到磁盘... pg_basebackup: renaming backup_manifest.tmp to backup_manifest pg_basebackup: 基础备份已完成 ❯ ls /pg_basebackup  24585.tar  base.tar 󰡯 backup_manifest  pg_wal.tar 恢复 首先删除所有文件,方便下面测试 [postgres@desktop-f5s26of ~]$ cd data [postgres@desktop-f5s26of data]$ ls base pg_multixact pg_subtrans postgresql.conf global pg_notify pg_tblspc postmaster.opts pg_commit_ts pg_replslot pg_twophase postmaster.pid pg_dynshmem pg_serial PG_VERSION tp_data pg_hba.conf pg_snapshots pg_wal pg_ident.conf pg_stat pg_xact pg_logical pg_stat_tmp postgresql.auto.conf [postgres@desktop-f5s26of data]$ rm -r ./* [postgres@desktop-f5s26of data]$ ls 之后进行恢复 -- 将上面的base.tar和pg_wal.tar准备好 -- 将base.tar的内容解压到/data下 tar -xf base.tar -C ~/data/ -- 将pg_wal.tar解压到/archivedir目录下 tar -xf pg_wal.tar -C /archivedir [postgres@desktop-f5s26of ~]$ cd /pg_basebackup/ [postgres@desktop-f5s26of pg_basebackup]$ ls 24585.tar backup_manifest base.tar pg_wal.tar [postgres@desktop-f5s26of pg_basebackup]$ tar -xf base.tar -C ~/data/ [postgres@desktop-f5s26of pg_basebackup]$ tar -xf pg_wal.tar -C /archivedir/ 此时,我们发现/archiverdir目录下有一些文件,同时/data下面文件也恢复了 [postgres@desktop-f5s26of /archivedir]$ ls 󰡯 0000000100000000000000CC [postgres@desktop-f5s26of data]$ ls backup_label pg_logical pg_stat_tmp postgresql.auto.conf base pg_multixact pg_subtrans postgresql.conf global pg_notify pg_tblspc standby.signal pg_commit_ts pg_replslot pg_twophase tablespace_map pg_dynshmem pg_serial PG_VERSION tp_data pg_hba.conf pg_snapshots pg_wal pg_ident.conf pg_stat pg_xact 这时候物理配置文件已经恢复,但是需要进行配置一些文件 -- 打开postgresql.auto.conf文件,有以下内容 # Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command. primary_conninfo = 'user=postgres password=38324 channel_binding=prefer host=192.168.1.13 port=5432 sslmode=prefer sslnegotiation=postgres sslcompression=0 sslcertmode=allow sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable' 我们暂时不需要现有的内容直接注释掉已有内容 # Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command. # primary_conninfo = 'user=postgres password=38324 channel_binding=prefer host=192.168.1.13 port=5432 sslmode=prefer sslnegotiation=postgres sslcompression=0 sslcertmode=allow sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable' 添加新的内容,保证可以恢复指定位置的物理数据文件 # 指定归档位置 restore_command = 'cp /archivedir/%f %p' # 最大程度恢复 recovery_target = 'immediate' 这时候重启服务,进入psql,可以正常看到数据。 [postgres@desktop-f5s26of data]$ psql psql (18.1) Type "help" for help. postgres=# \dt List of tables Schema | Name | Type | Owner --------+---------+-------+---------- public | student | table | postgres (1 row) postgres=# select * from student postgres-# ; student_id | name ------------+------ 2 | bbb 3 | ccc 5 | 6 | 9999 | 999967867 | (6 rows) 但是当我们进行写入操作或者建表等操作,就会发现不允许我们做。 postgres=# create table tt(id int); ERROR: cannot execute CREATE TABLE in a read-only transaction postgres=# insert into student values(22); ERROR: cannot execute INSERT in a read-only transaction 这是因为物理恢复之后,数据库仍认为自己处于恢复模式,是只读的。因此我们需要执行以下函数pg_wal_replay_resume,恢复状态,即可正常执行写入操作。 postgres=# select pg_wal_replay_resume(); pg_wal_replay_resume ---------------------- (1 row) postgres=# insert into student values(22); INSERT 0 1 归档备份 先了解几个概念,在PostgreSQL有多个子进程来辅助一些操作 BgWriter进程:BgWriter是将内存中的数据写到磁盘中的一个辅助进程。当向数据库中执行写操作后,数据不会马上持久化到磁盘里。这个主要是为了提升性能。BgWriter会周期性的将内存中的数据写入到磁盘。但是这个周期时间,长了不行,短了也不行。 如果快了,I0操作频繁,效率慢。 如果慢了,有查询操作需要内存中的数据时,需要BgWriter现把数据从内存写到磁盘中,再提供给查询操作作为返回结果。会导致查询操作效率变低。。考虑一个问题: 事务提交了,数据没落到磁盘,这时,服务器宕机了怎么办? WalWriter进程:WAL就是write ahead log的缩写,说人话就是预写日志(redo log)。其实数据还在内存中时,其实已经写入到WAL日志中一份,这样一来,即便BgWriter进程没写入到磁盘中时,数据也不会存在丢失的问题。 WAL能单独做备份么?单独不行! 但是WAL日志有个问题,这个日志会循环使用,WAL日志有大小的线程,只能保存指定时间的日志信息,如果超过了,会覆盖之前的日志。 PgArch进程:WAL日志会循环使用,数据会丢失。没关系,还有一个归档的进程,会在数据覆盖前,将WAL日志备份出来,PostgreSOL也提供了一个全量备份的操作,可以根据WAL日志, 备份 在postgres配饰文件目录目录下,可以看到pg_wal目录: [postgres@desktop-f5s26of data]$ ls base pg_multixact pg_subtrans postgresql.conf global pg_notify pg_tblspc postmaster.opts pg_commit_ts pg_replslot pg_twophase postmaster.pid pg_dynshmem pg_serial PG_VERSION tp_data pg_hba.conf pg_snapshots pg_wal pg_ident.conf pg_stat pg_xact pg_logical pg_stat_tmp postgresql.auto.conf [postgres@desktop-f5s26of pg_wal]$ ls 0000000100000000000000C4 0000000100000000000000E5 0000000100000000000000C5 0000000100000000000000E6 0000000100000000000000C6 0000000100000000000000E7 0000000100000000000000C7 0000000100000000000000E8 0000000100000000000000C8 0000000100000000000000E9 0000000100000000000000C9 0000000100000000000000EA 0000000100000000000000CA 0000000100000000000000EB 0000000100000000000000CB 0000000100000000000000EC 0000000100000000000000CC 0000000100000000000000ED 0000000100000000000000CD 0000000100000000000000EE 0000000100000000000000CE 0000000100000000000000EF 0000000100000000000000CF 0000000100000000000000F0 0000000100000000000000D0 0000000100000000000000F1 0000000100000000000000D1 0000000100000000000000F2 0000000100000000000000D2 0000000100000000000000F3 0000000100000000000000D3 0000000100000000000000F4 0000000100000000000000D4 0000000100000000000000F5 0000000100000000000000D5 0000000100000000000000F6 0000000100000000000000D6 0000000100000000000000F7 0000000100000000000000D7 0000000100000000000000F8 0000000100000000000000D8 0000000100000000000000F9 0000000100000000000000D9 0000000100000000000000FA 0000000100000000000000DA 0000000100000000000000FB 0000000100000000000000DB 0000000100000000000000FC 0000000100000000000000DC 0000000100000000000000FD 0000000100000000000000DD 0000000100000000000000FE 0000000100000000000000DE 0000000100000000000000FF 0000000100000000000000DF 000000010000000100000000 0000000100000000000000E0 000000010000000100000001 0000000100000000000000E1 000000010000000100000002 0000000100000000000000E2 000000010000000100000003 0000000100000000000000E3 archive_status 0000000100000000000000E4 summaries 这些文件如何区分呢?每8位一组,16进制标识。 00000001 00000000 000000C4 时间线 逻辑id 物理id 查询当前使用的wal postgres=# select pg_current_wal_lsn(); pg_current_wal_lsn -------------------- 0/C4715C58 (1 row) postgres=# select pg_walfile_name('0/C4715C58'); pg_walfile_name -------------------------- 0000000100000000000000C4 (1 row) 默认归档备份不开启,我们可以找data/postgre.conf文件设置,设置完成记得重启服务。 wal_level = replica fsync = on archive_mode = on archive_command = 'test ! -f /archivedir/%f && cp %p /archivedir/%f' 命令操作: test ! -f /archivedir/%f # 检查条件 && # 逻辑与(条件满足才执行) cp %p /archivedir/%f # 执行拷贝 %p: 源文件路径(完整路径) $PGDATA/pg_wal/000000010000000100000001 %f: 文件名 000000010000000100000001 正常归档流程 1. PostgreSQL 生成 WAL 文件 2. WAL 文件写满(16MB)或被切换 3. 触发归档进程 4. 执行 archive_command: a. test ! -f /archivedir/000000010000000100000001 b. 如果文件不存在 → 执行 cp 命令 c. 如果文件已存在 → 跳过(避免重复) 5. 如果命令返回 0(成功): - PostgreSQL 标记该 WAL 文件可被回收 6. 如果命令返回非 0(失败): - PostgreSQL 会定期重试 - WAL 文件会一直保留 实际执行归档过程 # 假设当前 WAL 文件是:0000000100000001000000AB # PostgreSQL 内部执行: test ! -f /archivedir/0000000100000001000000AB # 如果返回 true(文件不存在),执行: cp $PGDATA/pg_wal/0000000100000001000000AB /archivedir/0000000100000001000000AB # 完整命令在 shell 中执行: sh -c 'test ! -f /archivedir/0000000100000001000000AB && cp /var/lib/postgresql/12/main/pg_wal/0000000100000001000000AB /archivedir/0000000100000001000000AB' 如何测试,真的开启了归档了呢?我们提过还有一个归档的进程,会在数据覆盖前,将WAL日志备份出来.因此我们需要让pg可以切换日志,那么就要有大量的写操作,导致切换日志。 create table test_archive( id int ); -- 查询当前的归档位置 select pg_walfile_name(pg_current_wal_lsn()); -- 插入40万条数据 insert into test_archive values(generate_series(1,400000)); -- 再次查询当前的归档位置 select pg_walfile_name(pg_current_wal_lsn()); 这时候我们发现,文件从C5切换到了C7,日志切换了。 postgres=# select pg_walfile_name(pg_current_wal_lsn()); pg_walfile_name -------------------------- 0000000100000000000000C5 (1 row) postgres=# insert into test_archive values(generate_series(1,400000)); INSERT 0 400000 postgres=# select pg_walfile_name(pg_current_wal_lsn()); pg_walfile_name -------------------------- 0000000100000000000000C7 (1 row) 这时候我们去指定的归档地点查看实际文件 ❯ cd /archivedir ❯ ls 󰡯 0000000100000000000000C5 󰡯 0000000100000000000000C6 我们发现确实存储成功了。 恢复(PITR) 时间点恢复,比如每天晚上24点做全备份,第二天14数据被删除。我们需要恢复到昨晚24点的未删除状态。 如果使用物理备份,也就是全量备份,会丢失很多数据。 而如果使用PITR,有昨晚24点->第二天14点的所有数据信息,我们指定数据恢复到制定的事务id或指定的时间点,从事实现数据完整恢复。 先进行全备操作(24:00) pg_basebackup -D /pg_basebackup -Ft -Pv -Upostgres -h 192.168.1.13 -p 5432 -R 之后进行写入操作 insert into student values(24); 误删操作 delete from student; 恢复数据 将当前服务的全部干掉,按照前面的套路全备恢复,停掉服务 su - postgres cd ~/data/ rm -rf * sudo systemctl stop postgresql 之后进行恢复 [postgres@desktop-f5s26of pg_basebackup]$ tar -xf base.tar -C ~/data/ [postgres@desktop-f5s26of pg_basebackup]$ tar -xf pg_wal.tar -C /archivedir/ 来到归档目录,查看归档日志,使用pg_waldump查询 cd /archivedir pg_waldump 0000000100000000000000CC ❯ sudo pg_waldump 0000000100000000000000CC rmgr: XLOG len (rec/tot): 30/ 30, tx: 0, lsn: 0/CC000028, prev 0/CB0000A0, desc: CHECKPOINT_REDO wal_level replica rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/CC000048, prev 0/CC000028, desc: RUNNING_XACTS nextXid 826 latestCompletedXid 825 oldestRunningXid 826 rmgr: XLOG len (rec/tot): 114/ 114, tx: 0, lsn: 0/CC000080, prev 0/CC000048, desc: CHECKPOINT_ONLINE redo 0/CC000028; tli 1; prev tli 1; fpw true; wal_level replica; xid 0:826; oid 32791; multi 1; offset 0; oldest xid 744 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 826; online rmgr: XLOG len (rec/tot): 34/ 34, tx: 0, lsn: 0/CC0000F8, prev 0/CC000080, desc: BACKUP_END 0/CC000028 rmgr: XLOG len (rec/tot): 24/ 24, tx: 0, lsn: 0/CC000120, prev 0/CC0000F8, desc: SWITCH 找到你要恢复的节点的id 这时候修改data/postgresql.auto.conf,下面是之前填写的内容,我们修改最大程度恢复为,指定事务id恢复。注释immediate # 指定归档位置 restore_command = 'cp /archivedir/%f %p' # 最大程度恢复 recovery_target = 'immediate' # 指定归档位置 restore_command = 'cp /archivedir/%f %p' # 最大程度恢复 # recovery_target = 'immediate' 同时我们打开postgresql.conf搜索recovery,定位#recovery_target_xid = ''选项,告诉我们是用来指定事务id的,我们这时候复制这个选项到文件postgresql.auto.conf中 # 指定归档位置 restore_command = 'cp /archivedir/%f %p' # 最大程度恢复 # recovery_target = 'immediate' recovery_target_xid = '718' 保存之后,正常启动postgre服务即可 systemctl start postgresql psql 注意 我们这里备份常常使用postgresql.conf和postgresql.auto.conf文件,加载顺序如下 # 实际加载顺序: 1. postgresql.conf # 主配置 2. 包含的文件 (include_dir/*.conf) # 按文件名排序 3. postgresql.auto.conf # 自动配置(最后,优先级最高) 也就是每次服务启动都会执行一次 postgresql.auto.conf ,为了防止每次启动都会导致一次恢复操作,我们可以在每次恢复完之后,立马清除 auto 文件. seq -i 's/^/# /' data/postgresql.auto.conf