WAL日志
1.WAL概述
PG WAL(Write-Ahead Logging)日志是PostgreSQL数据库中的一种重要机制,用于保证数据库的完整性和数据恢复。
1.1定义与功能
WAL日志是PostgreSQL的持久性技术,它将所有对数据库的修改操作(如INSERT、UPDATE、DELETE等)记录到一个称为WAL日志的文件中。这些记录是在对数据库中的数据进行任何修改之前进行的,即“先记后做”。这种机制确保了即使系统崩溃或发生意外停机,也可以使用WAL日志来恢复数据库的一致性状态。
1.2工作原理
- 事务开始:当一个事务开始时,PostgreSQL会记录下相关操作。
- 写入WAL:在事务中对数据库做出的任何修改首先会被写入WAL日志。这些日志被顺序写入,通常存储在磁盘上的预定义路径中(如pg_wal或pg_xlog目录)。
- 刷新到磁盘:在事务提交之前,涉及的所有WAL记录必须首先被刷新(写入)到磁盘上。这确保了即使在发生故障时,这些修改也不会丢失。
- 背景写入:数据库的后台写入进程(如checkpointing和background writer)会将数据从内存中写入磁盘,但不必在每次事务提交时立即这样做,因为已经有了WAL记录。
没有日志的insert
将数据从磁盘读取到缓冲区,然后插入数据,提交直接在缓冲区,没有将数据刷新到磁盘,当发生故障时,数据丢失
有日志的WAL
LSN(Log Sequence Number)是用于标识和跟踪事务日志的一种方式,用于标识特定记录的位置
使用WAL日志恢复数据
create unlogged table t1(id int);
解决坏一致问题,当页有问题,怎么解决,看下面的全页写
2.全页写
全页写(Full Page Write,FPW)是PostgreSQL数据库中的一种日志记录机制,用于确保在数据库恢复过程中,能够恢复修改过的数据页,即使在写入过程中发生故障导致部分页面数据损坏
2.1全页写的工作原理 :
当数据库在检查点(checkpoint)之后第一次修改一个页面时,整个页面会被写入WAL(Write-Ahead Logging)日志中,而不仅仅是修改的部分。
这种机制确保了在恢复过程中,遇到损坏的页面时,可以从WAL中恢复完整的页面数据,而不需要从数据文件中读取可能已经损坏的部分
2.2全页写的模式 :
非强制模式 :这是默认模式。在最后一次检查点之后,第一次修改的数据块会进行全页写,之后再次修改时不会进行全页写,直到下一次检查点发生。通过设置full_page_writes=on可以启用非强制模式。
强制模式 :当使用pg_basebackup工具对数据库进行备份时,会自动执行强制模式。在备份期间,任何被修改的数据库块都会被写入WAL中,无论是否是第一次修改或是否有检查点。执行pg_start_backup函数时,系统也会进入全页写模式,执行pg_stop_backup后停止
全页写
全页写恢复机制
3.WAL物理结构与逻辑结构
3.1WAL物理结构
文件命名与格式
- 在PostgreSQL中,WAL文件默认以16MB为单位进行切分,每个文件称为WAL段。
- WAL文件名由24个字符组成(每个字符以十六进制数表示),命名规则包括时间线ID(8位)、逻辑ID(8位)和逻辑段号(8位,但通常只需最后2位即可表示,因为每个逻辑ID包含256个16M的物理WAL文件)。
- 例如,文件名“000000010000000000000001”表示时间线ID为1,逻辑ID为0,是本逻辑ID的第1个WAL文件。
文件内部布局
- WAL文件内部被切分为8192字节(8K)的页面。
- 第一个页面包含由结构体XLogLongPageHeaderData定义的头数据,而其他页面则包含结构体XLogPageHeaderData定义的头数据。
- 在页头之后,是以降序写入的XLOG记录。
存储路径
- 在PostgreSQL中,WAL文件默认存储在$PGDATA/pg_wal/目录下(在PostgreSQL 10及之前版本,该目录名为pg_xlog)。
事务日志与WAL段文件
wal日志文件命名规则:
我们看到的wal日志是这样的:000000010000000100000092
- 其中前8位:00000001表示timeline;
- 中间8位:00000001表示logid;
- 最后8位:00000092表示logseg
wal日志LSN编号规则:
1/920001F8(高32位/低32位)
select pg_current_wal_lsn();
3.1.1WAL数据内部布局
PG把日志文件划分为N个大小为16M(默认值)的WAL segment file,pg_resetwal --wal-segsize=64可以将WAL日志文件大小设置为64MB
WAL日志结构
WAL日志包含的数据类型
3.1.2WAL数据写进程
查看对应的wal日志配置 wal_buffers=512k 默认值为shared_buffers大小的1/32,16284k=16M
elect name,setting from pg_settings where name like '%share%';name | setting
----------------------------+---------dynamic_shared_memory_type | windowsshared_buffers | 16384postgres=# select name,setting from pg_settings where name like '%wal%';name | setting
------------------------------+---------------max_wal_senders | 0max_wal_size | 64min_wal_size | 5wal_block_size | 8192wal_buffers | 512wal_compression | offwal_keep_segments | 0wal_level | minimalwal_log_hints | offwal_receiver_status_interval | 10wal_receiver_timeout | 60000wal_retrieve_retry_interval | 5000wal_segment_size | 2048wal_sender_timeout | 60000wal_sync_method | open_datasyncwal_writer_delay | 200wal_writer_flush_after | 128
(17 行记录)
什么时候触发写日志
-
提交事务时 :当一个事务被提交时,日志编写器(LGWR)会将事务日志信息写入联机日志文件。这是数据库管理系统(DBMS)确保数据一致性和恢复能力的关键机制之一。
-
日志缓冲区满时 :当日志缓冲区达到其容量的1/3时,LGWR会被触发以将日志信息写入磁盘。
-
日志切换时 :在数据库进行日志切换时,即从一个日志文件切换到下一个日志文件时,LGWR也会被触发进行日志写入。WAL段写满、执行pg_switch_wal命令、开启归档且达到archive_timeout阀值
-
用户操作触发 :用户执行commit或rollback语句时,会触发日志记录。这是因为这些操作标志着事务的结束,需要将相关信息写入日志以确保事务的持久性和可恢复性。
3.2WAL逻辑结构
3.2.1记录内容
WAL中记录的日志条目是事务记录(原始DML SQL)的格式化版本,而不是直接记录原始SQL。
XLOG记录的内容包括备份块、DML操作的XLOG记录、检查点操作的XLOG记录等。
3.2.2写入机制
所有数据块在进行修改时,都在数据缓冲区中进行。所有操作的日志将首先记录在日志缓冲区中。
当事务提交之后,日志缓冲区的内容将写入磁盘中的WAL文件。
WAL writer是一个后台进程,用于定期检查WAL缓冲区,并将所有未写入的XLOG记录写入WAL段。此过程的目的是避免XLOG记录的突发写入。
3.2.3日志切换
WAL文件切换会在以下情况下发生:
- WAL文件已经写满、
- 执行pg_switch_wal()函数(在PostgreSQL 10及之后版本)、
- 启用归档archive_mode且超过archive_timeout设置值。
切换后的段文件通常会被回收(重命名或重用)以供将来使用,如果不需要,也可能会被删除。
postgres=# \d pg_proc;数据表 "pg_catalog.pg_proc"栏位 | 类型 | 修饰词
-----------------+--------------+--------proname | name | 非空pronamespace | oid | 非空proowner | oid | 非空prolang | oid | 非空procost | real | 非空prorows | real | 非空provariadic | oid | 非空protransform | regproc | 非空proisagg | boolean | 非空proiswindow | boolean | 非空prosecdef | boolean | 非空proleakproof | boolean | 非空proisstrict | boolean | 非空proretset | boolean | 非空provolatile | "char" | 非空proparallel | "char" | 非空pronargs | smallint | 非空pronargdefaults | smallint | 非空prorettype | oid | 非空proargtypes | oidvector | 非空proallargtypes | oid[] |proargmodes | "char"[] |proargnames | text[] |proargdefaults | pg_node_tree |protrftypes | oid[] |prosrc | text | 非空probin | text |proconfig | text[] |proacl | aclitem[] |
索引:"pg_proc_oid_index" UNIQUE, btree (oid)"pg_proc_proname_args_nsp_index" UNIQUE, btree (proname, proargtypes, pronamespace)postgres=#
postgres=# select proname from pg_proc where proname like '%wal%';proname
--------------------------pg_stat_get_wal_senderspg_stat_get_wal_receiver
(2 行记录)# 正常有个pg_watch_wal
select pg_switch_wal();
3.2.4检查点与日志管理
检查点是一个定期发生的数据库状态保存点,它确保所有在检查点之前提交的事务的更改都已写入数据文件。
在检查点期间,PostgreSQL会预估并准备下一个检查点周期所需的WAL段文件数,并基于前一个检查点周期中消耗的文件数量来进行文件保留或回收。
重要的参数包括max_wal_size(控制WAL目录的最大大小)和WAL_keep_segments(控制当前机器WAL日志文件最少保留个数)等。
3.2.5WAL核心参数
- min_wal_size
定义 :设置WAL文件保留的最小尺寸。在检查点(checkpoint)之后,用于保留未来循环使用的WAL文件。
默认值 :80MB(具体值可能因PostgreSQL版本和配置而异)。此值必须大于segment size的两倍,16M*2=32M
- max_wal_size
定义 :两个检查点(checkpoint)之间,WAL文件可增长的最大大小。
默认值 :无明确默认值,但通常会根据系统需求和性能进行调整。
- wal_keep_segments
定义 :控制WAL文件在达到max_wal_size后保留的秒数3。在达到最大尺寸后,旧的WAL文件会在这个时间后被删除,以释放空间。
默认值 :无明确默认值,但通常会根据系统需求和性能进行调整
当调整为20M小于32M会报错
4. WAL管理
4.1 WAL的基本概念
WAL是一种用于数据库系统以保证数据一致性和持久性的技术。在使用WAL的系统中,所有的修改在生效之前都要先写入log文件中。这些log文件通常包含了redo和undo信息,以便在系统崩溃或发生故障时,能够通过重新执行这些日志记录来恢复数据库到一致的状态。
4.2 WAL的管理策略
1.日志写入策略:
- 对于对象的任何变更,都要首先记入日志。
- 日志必须要先于对象被写入磁盘,以确保在发生故障时,日志记录能够作为恢复数据库的依据。
2.日志切换与归档:
- 当WAL段文件被填满或达到预设的切换条件时,会触发日志切换,生成新的WAL段文件。
- 在归档模式下,切换后的WAL段文件会被复制到归档区域进行保存,以便后续可能需要的数据恢复或分析。
3.日志删除与回收:
- 旧的、不再需要的WAL段文件会被删除或回收,以释放存储空间。
- 删除或回收的时机通常基于检查点的完成和预设的保留策略。
4.4 WAL日志大小变更步骤
停库
pg_resetwal -D $PGDATA --wal_segsize=64
启库
4.5 WAL自动清理场景
超过了max_wal_size
触发了检查点(手工、自动及超时)
正常停库
自动清理并不会直接删除对应的wal日志,它会重命名
4.6WAL归档日志
4.6.1WAL归档的定义
WAL归档是指将数据库系统中的WAL日志文件备份到指定的存储位置,以便在数据库系统发生故障时能够通过这些归档的日志文件进行数据恢复。
4.6.2 WAL归档的作用
- 数据恢复:在数据库系统发生故障时,可以通过归档的WAL日志文件恢复数据,确保数据的完整性和一致性。
- 在线备份:WAL归档支持在线备份,即在不停止数据库服务的情况下进行备份操作。
- 时间点恢复:通过归档的WAL日志文件,可以实现数据库的时间点恢复,即恢复到某个特定的时间点。
4.6.3 WAL归档的配置
在PostgreSQL等数据库系统中,WAL归档的配置通常涉及以下几个参数:
- wal_level:决定了写入WAL的信息量。对于归档模式,通常需要将其设置为replica或更高的级别。
- archive_mode:用于设置是否开启归档模式。当设置为on时,表示开启归档模式。
- archive_command:指定归档WAL日志的命令。该命令通常是一个shell脚本或命令,用于将WAL日志文件复制到指定的存储位置。
# - Archiving -#archive_mode = off # enables archiving; off, on, or always# (change requires restart)
#archive_command = '' # command to use to archive a logfile segment# placeholders: %p = path of file to archive# %f = file name only# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
#archive_timeout = 0 # force a logfile segment switch after this# number of seconds; 0 disables
4.6.4 WAL归档的流程
- 生成WAL日志文件:数据库系统在执行事务时,会先将变更写入WAL日志缓冲区,然后在适当的时候将其刷新到WAL日志文件中。
- 触发归档操作:当WAL日志文件达到一定大小或满足其他归档条件时,数据库系统会触发归档操作。
- 执行归档命令:数据库系统执行配置的archive_command命令,将WAL日志文件复制到指定的存储位置。
- 更新状态信息:归档操作完成后,数据库系统会更新相关的状态信息,以便后续的恢复操作。
4.6.5 WAL归档的注意事项
- 存储空间:归档的WAL日志文件会占用大量的存储空间,因此需要合理规划存储资源。
- 备份策略:建议定期备份归档的WAL日志文件,以防止数据丢失。
- 监控和报警:建议对WAL归档过程进行监控,并在出现异常时及时报警和处理。
- 恢复测试:定期进行数据恢复测试,以确保归档的WAL日志文件能够正常用于数据恢复。