我们了解了缓冲区缓存的结构,并得出了结论,如果所有缓存内容由于故障而丢失,则需要预写日志(WAL)来恢复。由于不定期会执行检查点,所需WAL文件的大小和恢复时间会受到限制。
在之前的文章中,我们已经回顾了许多与WAL相关的重要设置。在本文(本系列的最后一篇)中,我们将讨论尚未解决的WAL设置问题:WAL级别及其用途,以及预写日志记录的可靠性和性能。
WAL日志级别
WAL的主要任务是确保故障后的恢复。但是,一旦我们必须维护日志,我们还可以通过向日志中添加更多信息使其适应其他任务。有几个日志记录级别。由wal_level
参数指定级别,下一个级别包括上一级别的所有内容以及新内容。
Minimal 级别
wal_level=minimal
是最低级别,确保仅在发生故障后恢复。为节省空间,不记录与批量数据处理相关的操作(如 CREATE TABLE AS SELECT
或CREATE INDEX
)。相反,这些数据会立即写入磁盘,新对象会添加到系统目录中,并在事务提交时可见。如果在执行操作时发生故障,已写入的数据将保持不可见,并且不会违反一致性规则。如果操作完成后出现故障,所需的一切都已在磁盘上,不需要记录。
让我们看一看。首先,我们将设置必要的级别(为此,我们还需要更改另一个参数-max_wal_senders
)。
=> ALTER SYSTEM SET wal_level = minimal;=> ALTER SYSTEM SET max_wal_senders = 0;student$ sudo pg_ctlcluster 11 main restart
请注意,级别的更改需要重新启动服务。
让我们记住当前的WAL的位置:
=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/353927BC(1 row)
现在,让我们执行一个表的创建(CREATE TABLE AS SELECT
),并再次记住WAL的位置。在这种情况下,SELECT
操作符检索的数据量根本不重要,因此一行就足够了。
=> CREATE TABLE wallevel ASSELECT 1 AS n;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/353A7DFC(1 row)
让我们使用pg_waldump
程序查看WAL记录。
postgres$ /usr/lib/postgresql/11/bin/pg_waldump -p /var/lib/postgresql/11/main/pg_wal -s 0/353927BC -e 0/353A7DFC
当然,一些细节在不同的返回中可能会有所不同,但在本例中,我们得到以下信息。Heap2
管理器的记录与vacuuming有关,这里它位于系统目录表的页面vacuum中(系统对象很容易用肉眼通过rel
中的一个小数字来区分):
rmgr: Heap2 len (rec/tot): 59/ 7587, tx: 0, lsn: 0/353927BC, prev 0/35392788, desc: CLEAN remxid 101126, blkref #0: rel 1663/16386/1247 blk 8 FPW
获取要创建的表的下一个OID的记录如下:
rmgr: XLOG len (rec/tot): 30/ 30, tx: 0, lsn: 0/35394574, prev 0/353927BC, desc: NEXTOID 82295
这是表的纯创建:
rmgr: Storage len (rec/tot): 42/ 42, tx: 0, lsn: 0/35394594, prev 0/35394574, desc: CREATE base/16386/74103
但是将数据插入到表中不会被WAL记录。多条记录跟随行插入到不同的表和索引中-通过这种方式,PostgreSQL将所创建表上的信息写入系统目录(以简写形式提供):
rmgr: Heap len (rec/tot): 203/ 203, tx: 101127, lsn: 0/353945C0, prev 0/35394594, desc: INSERT off 71, blkref #0: rel 1663/16386/1247 blk 8rmgr: Btree len (rec/tot): 53/ 685, tx: 101127, lsn: 0/3539468C, prev 0/353945C0, desc: INSERT_LEAF off 37, blkref #0: rel 1663/16386/2703 blk 2 FPW...rmgr: Btree len (rec/tot): 53/ 2393, tx: 101127, lsn: 0/353A747C, prev 0/353A6788, desc: INSERT_LEAF off 10, blkref #0: rel 1664/0/1233 blk 1 FPW
最后是事务提交:
rmgr: Transaction len (rec/tot): 34/ 34, tx: 101127, lsn: 0/353A7DD8, prev 0/353A747C, desc: COMMIT 2019-07-23 18:59:34.923124 MSK
Replica 级别
当我们从备份中恢复PostgreSQL实例时,我们从文件系统的某些状态开始,通过回放归档的WAL记录,逐渐将数据带到恢复的目标点。这类记录的数量可能相当大(例如,几天的记录),也就是说,恢复期将跨越多个检查点,而不是一个检查点。因此,很明显,minimal
级别是不够的——如果一个操作没有记录,我们将不知道是否需要重做它。要支持从备份还原,WAL日志必须记录所有操作。
复制也是如此:未记录的所有内容都不会发送到副本,也不会重放。希望在副本上运行查询会使情况更加复杂。
首先,我们需要关于主上产生的独占咨询锁的信息,因为它们可能会与副本上的查询冲突。这些锁将被写入wal,然后startup进程将它们应用到副本上。
其次,我们需要创建数据快照,要做到这一点,正如我们所记得的,需要有关正在执行的事务的信息。对于副本,不仅意味着本地事务,还意味着主的事务。提供此信息的唯一方法是不时记录WAL日志(每15秒一次)。
确保从备份恢复和物理复制可能性的WAL级别由WAL_level=replica
的值设置。(在9.6版之前,有两个独立的级别可用—archive
和hot_standby
—但后来它们合并了。)
从PostgreSQL 10开始使用这个级别作为默认级别(而之前是minimal
级别)。因此,让我们将参数恢复为默认值:
=> ALTER SYSTEM RESET wal_level;=> ALTER SYSTEM RESET max_wal_senders;student$ sudo pg_ctlcluster 11 main restart
删除表并重新执行与上次完全相同的步骤顺序:
=> DROP TABLE wallevel;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/353AF21C(1 row)=> CREATE TABLE wallevel ASSELECT 1 AS n;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/353BE51C(1 row)
现在让我们检查一下WAL记录。
postgres$ /usr/lib/postgresql/11/bin/pg_waldump -p /var/lib/postgresql/11/main/pg_wal -s 0/353AF21C -e 0/353BE51C
Vacuuming、获取OID、创建表并在系统目录中注册-与之前相同:
rmgr: Heap2 len (rec/tot): 58/ 58, tx: 0, lsn: 0/353AF21C, prev 0/353AF044, desc: CLEAN remxid 101128, blkref #0: rel 1663/16386/1247 blk 8rmgr: XLOG len (rec/tot): 30/ 30, tx: 0, lsn: 0/353AF258, prev 0/353AF21C, desc: NEXTOID 82298rmgr: Storage len (rec/tot): 42/ 42, tx: 0, lsn: 0/353AF278, prev 0/353AF258, desc: CREATE base/16386/74106rmgr: Heap len (rec/tot): 203/ 203, tx: 101129, lsn: 0/353AF2A4, prev 0/353AF278, desc: INSERT off 73, blkref #0: rel 1663/16386/1247 blk 8rmgr: Btree len (rec/tot): 53/ 717, tx: 101129, lsn: 0/353AF370, prev 0/353AF2A4, …rmgr: Btree len (rec/tot): 53/ 2413, tx: 101129, lsn: 0/353BD954, prev 0/353BCC44, desc: INSERT_LEAF off 10, blkref #0: rel 1664/0/1233 blk 1 FPW
这是新的东西。与Standby
管理器相关的排他锁记录-这里是事务ID上的锁:
rmgr: Standby len (rec/tot): 42/ 42, tx: 101129, lsn: 0/353BE2D8, prev 0/353BD954, desc: LOCK xid 101129 db 16386 rel 74106
这是表中的行插入记录(将文件号rel
与CREATE
记录中的文件号rel
进行比较):
rmgr: Heap len (rec/tot): 59/ 59, tx: 101129, lsn: 0/353BE304, prev 0/353BE2D8, desc: INSERT+INIT off 1, blkref #0: rel 1663/16386/74106 blk 0
这是提交记录:
rmgr: Transaction len (rec/tot): 421/ 421, tx: 101129, lsn: 0/353BE340, prev 0/353BE304, desc: COMMIT 2019-07-23 18:59:37.870333 MSK; inval msgs: catcache 74 catcache 73 catcache 74 catcache 73 catcache 50 catcache 49 catcache 7 catcache 6 catcache 7 catcache 6 catcache 7 catcache 6 catcache 7 catcache 6 catcache 7 catcache 6 catcache 7 catcache 6 catcache 7 catcache 6 snapshot 2608 relcache 74106 snapshot 1214
还有一条记录与Standby
管理器相关,该记录不时出现,通知此时正在执行的事务,与已完成的事务无关:
rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/353BE4E8, prev 0/353BE340, desc: RUNNING_XACTS nextXid 101130 latestCompletedXid 101129 oldestRunningXid 101130
Logical 级别
最后,最后一个级别由wal_level=logical
的值指定,额外再提供逻辑解码和逻辑复制。必须作为发布端打开它。
从WAL记录的角度来看,此级别实际上与replica
相同:添加与复制源相关的记录,以及应用程序可以添加到WAL的任意逻辑记录。但逻辑解码主要取决于正在执行的事务的信息,因为需要创建数据快照来跟踪系统目录的更改。
写日志的可靠性
显然,日志记录技术必须是可靠的,并确保在任何情况下都能恢复(当然,与数据存储介质的损坏无关)。许多事情会影响可靠性,其中我们将讨论缓存、数据损坏和写入的原子性。
缓存
多个缓存阻碍了数据进入非易失性存储器(如硬盘盘片)。
如果程序(本例中为PostgreSQL)要求操作系统(OS)在磁盘上写入内容,则操作系统会将数据传输到其RAM缓存。写入实际上是异步进行的,具体取决于操作系统的I/O调度程序的设置。
当操作系统决定写入数据时,它们会进入存储器(硬盘)的缓存。存储器的电子设备也可以推迟写入,例如,通过将更高效的数据分组在一起写入。如果使用RAID控制器,则会在操作系统和磁盘之间增加一个缓存级别。
因此,如果不采取特殊措施,数据何时以可靠的方式保存是绝对不清楚的。通常情况下,这没有什么区别,但在一些关键领域,PostgreSQL必须确保数据写入具有适当的可靠性。这主要是日志记录(如果WAL记录未到达磁盘,它将和其余缓存内容一起丢失)和检查点(我们必须确保脏页写入磁盘)。但也有其他情况,例如在minimal
级别执行不记录日志的操作等等。
操作系统提供了确保数据立即写入非易失性存储的功能。有几个选项,但可以把它们减少到两个主要选项:要么在写入后执行同步调用(fsync
、fdatasync
),要么在打开文件(或写入文件)后设置一个特殊标志,指示需要同步,甚至需要绕过操作系统缓存直接写入。
至于WAL,pg_test_fsync
程序允许我们选择最适合特定操作系统和特定文件系统的方法,该方法在wal_sync_method
参数中指定。普通文件使用fsync
进行同步。
一个微妙的点是,在选择方法时,我们需要考虑硬件特性。例如:如果使用使用battery-backup unit(BBU)的控制器,我们没有理由不使用控制器的缓存,因为BBU可以在断电时保存数据。
在任何情况下,同步都是非常昂贵的,而且执行同步的次数最多是绝对必要的。
通常,您可以关闭同步(fsync
参数负责此操作),但在这种情况下,您必须忘记存储的可靠性。通过关闭fsync
,您同意数据可能会在任何时候不可逆转地丢失。可能,该参数唯一合理的使用情况是,当数据可以从不同的源轻松恢复时,通过关闭fsync
获得性能的临时提高。
日志损坏
硬件不完善,数据在存储器中损坏,等等。一些错误是在硬件级别处理的,但有些则不是。
为了快速检测问题,WAL记录中提供了校验和。
数据页也可以通过校验和进行保护。之前,这只能在集群初始化时完成,但在PostgreSQL 12中,可以通过 pg_checksums
程序打开和关闭校验和(但仅当服务关闭时,而不是“运行中”)。
在生产环境中,无论计算和验证校验和的开销如何,校验和都必须启用。这降低了未及时检测到损坏的可能性。
它减少了概率,但没有消除。首先,只有在页面被访问时才验证校验和;因此,在损坏进入所有备份之前,可能无法检测到它。正是由于这个原因,
pg_probackup
在数据备份期间验证所有集群页面的校验和。其次,用零填充的页面被认为是正确的,因此,如果文件系统错误地“取消”了文件,这可以避免检测。第三,校验和只保护数据的主分支。其他分支和其他文件(例如,事务状态XACT)根本不受保护。
让我们看看它是如何工作的。首先,我们确保打开校验和(请注意,在类似Debian系统上安装的软件包中,默认情况下并非如此):
=> SHOW data_checksums;data_checksums----------------on(1 row)
data_checksums
参数是只读的。
这是我们表格所在的文件:
=> SELECT pg_relation_filepath('wallevel');pg_relation_filepath----------------------base/16386/24890(1 row)
让我们关闭服务器并用zero在页面上更改几个字节,例如:从标题中删除最后一条WAL记录的LSN。
student$ sudo pg_ctlcluster 11 main stoppostgres$ dd if=/dev/zero of=/var/lib/postgresql/11/main/base/16386/24890 oflag=dsync conv=notrunc bs=1 count=88+0 records in8+0 records out8 bytes copied, 0,0083022 s, 1,0 kB/s
通常,不需要关闭服务器。将页面刷新到磁盘并从缓存中逐出就足够了(否则,服务将继续在缓存中处理页面)。但这种情况更难再现。
现在我们启动服务器并尝试读取表。
student$ sudo pg_ctlcluster 11 main start=> SELECT * FROM wallevel;WARNING: page verification failed, calculated checksum 23222 but expected 50884ERROR: invalid page in block 0 of relation base/16386/24890
但是,如果无法从备份中恢复数据,我们该怎么办?ignore_checksum_failure
参数允许尝试读取表,当然,这会有获取损坏数据的风险。
=> SET ignore_checksum_failure = on;=> SELECT * FROM wallevel;WARNING: page verification failed, calculated checksum 23222 but expected 50884n---1(1 row)
当然,在这种情况下一切都很好,因为我们只伤害了头,而不是纯数据。
还有一点需要注意。打开校验和时,将WAL记录提示位(我们在前面讨论过),因为对任何位(即使是不重要的位)的更改都会导致校验和的更改。当校验和关闭时,wal_log_hints
参数负责wal日志提示位。
对提示位的更改总是记录为FPI(完整页面图像),这几乎增加了WAL的大小。在这种情况下,使用wal_compression
参数打开FPI的压缩是有意义的(该参数是在9.5版中添加的)。稍后我们将查看具体数字。
写入的原子性
最后,还有一个写入的原子性问题。数据库页占用的空间不小于8KB(可能是16或32KB),在较低的级别上,写入是以块的形式完成的,块的大小通常较小(通常是512字节或4KB)。因此,在断电的情况下,可以部分写入数据页。很明显,在恢复过程中,对这样的页面应用常规的WAL记录是没有意义的。
为了防止出现这种情况,PostgreSQL允许WAL在检查点周期开始后第一次更改页面时记录完整的页面映像(提示位更改时也会记录相同的映像)。full_page_write
参数控制这一点,默认情况下它处于打开状态。
如果恢复过程在WAL中遇到FPI,它会无条件地将映像写入磁盘(无需LSN检查):FPI更可靠,因为它与每个WAL记录一样,受校验和保护。正是这张可靠的正确映像,常规的WAL记录被应用于此。
虽然在PostgreSQL中,FPI不包括可用空间(我们在前面讨论了块结构),但FPI大大增加了WAL记录的生成量。如前所述,通过压缩FPI(使用wal_compression参数),可以改善这种情况。
为了深入了解如何更改WAL的大小,让我们使用pgbench
程序进行一个简单的实验。执行初始化:
student$ pgbench -i testdropping old tables...creating tables...generating data...100000 of 100000 tuples (100%) done (elapsed 0.15 s, remaining 0.00 s)vacuuming...creating primary keys...done.
full_page_writes
参数已打开:
=> SHOW full_page_writes;full_page_writes------------------on(1 row)
让我们执行一个检查点并立即运行一个测试30秒。
=> CHECKPOINT;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/38E04A08(1 row)student$ pgbench -T 30 teststarting vacuum...end.transaction type: TPC-B (sort of)scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1duration: 30 snumber of transactions actually processed: 26851latency average = 1.117 mstps = 895.006720 (including connections establishing)tps = 895.095229 (excluding connections establishing)=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/3A69C478(1 row)
获取WAL记录的大小:
=> SELECT pg_size_pretty('0/3A69C478'::pg_lsn - '0/38E04A08'::pg_lsn);pg_size_pretty----------------25 MB(1 row)
现在,让我们关闭full_page_writes
:
=> ALTER SYSTEM SET full_page_writes = off;=> SELECT pg_reload_conf();
我们重复这个实验。
=> CHECKPOINT;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/3A69C530(1 row)student$ pgbench -T 30 teststarting vacuum...end.transaction type: TPC-B (sort of)scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1duration: 30 snumber of transactions actually processed: 27234latency average = 1.102 mstps = 907.783080 (including connections establishing)tps = 907.895326 (excluding connections establishing)=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/3BE87658(1 row)
获得WAL记录的大小:
=> SELECT pg_size_pretty('0/3BE87658'::pg_lsn - '0/3A69C530'::pg_lsn);pg_size_pretty----------------24 MB(1 row)
是的,尺寸减小了,但不明显。
问题是集群是用数据页上的校验和初始化的,因此,当提示位发生变化时,必须记录FPI。这些数据(在上述情况下)约占总数的一半,您可以通过查看统计数据来确定:
postgres$ /usr/lib/postgresql/11/bin/pg_waldump --stats -p /var/lib/postgresql/11/main/pg_wal -s 0/3A69C530 -e 0/3BE87658Type N (%) Record size (%) FPI size (%)---- - --- ----------- --- -------- ---XLOG 1721 ( 1,03) 84329 ( 0,77) 13916104 (100,00)Transaction 27235 ( 16,32) 926070 ( 8,46) 0 ( 0,00)Storage 1 ( 0,00) 42 ( 0,00) 0 ( 0,00)CLOG 1 ( 0,00) 30 ( 0,00) 0 ( 0,00)Standby 4 ( 0,00) 240 ( 0,00) 0 ( 0,00)Heap2 27522 ( 16,49) 1726352 ( 15,76) 0 ( 0,00)Heap 109691 ( 65,71) 8169121 ( 74,59) 0 ( 0,00)Btree 756 ( 0,45) 45380 ( 0,41) 0 ( 0,00)-------- -------- --------Total 166931 10951564 [44,04%] 13916104 [55,96%]
删除零行以使表更紧凑。注意汇总行(总计),并将完整图像的大小(FPI大小)与正常记录的大小(记录大小)进行比较。
仅当文件系统和硬件本身确保写入原子性时,才能关闭full_page_writes
参数。但是,正如我们所看到的,它没有多大意义(只要打开校验和)。
现在让我们看看压缩有什么帮助。
=> ALTER SYSTEM SET full_page_writes = on;=> ALTER SYSTEM SET wal_compression = on;=> SELECT pg_reload_conf();
重复同样的实验。
=> CHECKPOINT;=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/3BE87710(1 row)student$ pgbench -T 30 teststarting vacuum...end.transaction type: TPC-B (sort of)scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1duration: 30 snumber of transactions actually processed: 26833latency average = 1.118 mstps = 894.405027 (including connections establishing)tps = 894.516845 (excluding connections establishing)=> SELECT pg_current_wal_insert_lsn();pg_current_wal_insert_lsn---------------------------0/3CBD3EA8(1 row)
获取WAL记录的大小:
=> SELECT pg_size_pretty('0/3CBD3EA8'::pg_lsn - '0/3BE87710'::pg_lsn);pg_size_pretty----------------13 MB(1 row)
结论:如果有许多FPI(由于校验和或full_page_writes
,几乎总是这样),尽管压缩会使用到cpu,但使用压缩还是有意义的。
性能
在正常工作期间,WAL文件按照一个接一个的顺序被连续写入。由于没有随机访问,即使是HDD磁盘也能正常工作。但是,这种负载与访问数据文件时的负载有很大不同。
因此,将WAL存储在单独的物理磁盘(或磁盘阵列)上通常是有益的。必须创建指向相应目录的符号链接,而不是$PGDATA/pg_wal
目录。
在某些情况下,不仅需要写入WAL文件,还需要读取WAL文件。第一个是发生故障后恢复的明确案例。第二个不那么琐碎。如果使用流复制,WAL记录仍在主的OS缓冲区中时,副本延迟接收WAL记录。在这种情况下,
walsender
进程必须从磁盘读取必要的数据。进行复制时,我们将对此进行更详细的讨论。
WAL以以下两种方式之一写入:
同步 — 在事务提交时,直到该事务的所有WAL记录都进入磁盘后,才能继续工作。
异步 — 事务立即完成,并且WAL在后台写入。
缺省情况下,synchronous_commit
参数处于打开状态,用于设置同步模式。
由于同步与实际的(即较慢的)输入/输出有关,因此尽可能少地进行同步是有好处的。为此,完成事务并写入WAL的后端进程会稍作暂停,这由commit_delay
参数定义。但这仅在系统具有不少于commit_siblings
活动事务的情况下才会发生。此行为依赖于这样的期望:在等待时间内,一些事务将完成,并且可以一次性同步它们。这类似于你摁住电梯门的方式,以便有人有时间进入。
默认情况下,commit_siblings = 5
,commit_delay = 0
,因此实际上没有等待。仅对于执行大量OLTP事务的系统,更改commit_delay
的值才有意义。
然后,将WAL的一部分刷新到所需的LSN位置(如果在等待时间内添加了新记录,则刷新更多)。刷新之后,事务被视为完成。
同步写入确保了持久性(ACID字母缩写中的字母D):如果事务已提交,其所有WAL记录都已在磁盘上,并且不会丢失。但一个缺点是同步写入会增加响应时间(COMMIT命令在同步结束之前不会返回控制),并降低系统性能。
您可以通过设置sync_commit = off
(或local
)来使写入变成异步。
当异步写入时,WAL记录将由wal writer进程刷新,该进程将交替工作并等待(等待时间由wal_writer_delay
参数指定,默认值为200 ms)。
该进程被唤醒后,它将检查自上次以来是否出现了完全填充的WAL页面。如果确实出现了,则该进程将忽略当前未填充到最后的页面,仅写入完全填充的页面。(但是,并非一次完成:写入到达高速缓存末尾时会停止,而下一次从高速缓存起始点开始。)
但是,如果没有任何页面被填满,则该进程将刷新当前的WAL页面(未填充到末尾)—要不然,唤醒后干嘛呢?
该算法旨在尽可能避免多次同步同一页面,这对于大量更新至关重要。
异步写入比同步写入更有效,因为更改的提交不等待WAL页面的写入。但是可靠性降低了:如果在提交和失败之间经过的时间少于3×wal_writer_delay
单位,则提交失败的数据可能会在失败的情况下丢失(使用默认设置,该时间稍长于半秒)。
在效率和可靠性之间并非一个简单的选择,要取决于系统管理员。
请注意:与关闭同步(fsync = off
)不同,异步模式不会使恢复变得不可能。万一发生故障,系统将恢复一致状态,但也许某些最后的事务将不存在。
可以为单独的事务设置synchronous_commit
参数。这样可以通过仅牺牲某些事务的可靠性来提高性能。例如金融交易必须同步进行,而聊天消息却可能使用异步。
实际上,两种模式可以协同工作。即使使用同步提交,长事务的WAL记录也将被异步写入,以释放WAL缓冲区。而且,如果在从缓冲区高速缓存中刷新页面期间,似乎还没有在磁盘上存储相应的WAL记录,那么它将以同步模式立即被刷新。
为了深入了解异步提交的好处,让我们尝试在此模式下重复pgbench
测试。
=> ALTER SYSTEM SET synchronous_commit = off;=> SELECT pg_reload_conf();student$ pgbench -T 30 teststarting vacuum...end.transaction type: TPC-B (sort of)scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1duration: 30 snumber of transactions actually processed: 45439latency average = 0.660 mstps = 1514.561710 (including connections establishing)tps = 1514.710558 (excluding connections establishing)
使用同步提交,我们每秒大约获得900个事务(tps),使用异步提交则获得1500 tps。不用说,在实际系统中的实际负载下,所占的比例会有所不同,但是很明显,对于短期交易而言,其影响可能是相当大的。
关于WAL日志的系列文章到此结束。




