码迷,mamicode.com
首页 > 数据库 > 详细

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(5)

时间:2015-08-19 22:38:52      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:

2.5 XLOG的内部结构

我们将使用事务贯穿本书,并让您在技术层面上更深地洞察事情是如果工作的,我们已经增加了这部分专门处理XLOG的内部工作机制。我们会尽量避免前往下降到C级,因为这将超出本书的范围,但我们会为您提供希望足够深的见解。

2.5.1 理解XLOG记录

对XLOG所做的更改是基于记录的。这意味着什么?让我们假设您在给一个表添加一行数据:

test=# INSERT INTO t_test VALUES (1, ‘hans‘);

INSERT 0 1

在这个例子中,我们正在插入一个含有两列的表。为了这个例子,我们要假定这两个列被索引。

记得我们之前了解到:XLOG的目的是为了保持这些数据文件安全。所以,这个操作将触发一系列的XLOG条目。首先,与表相关的数据文件将被写入。然后,索引相关的条目将被创建。最后一个COMMIT记录被发送到日志。

并不是所有的XLOG记录都是平等的:有各种类型的XLOG记录(例如,heap,btree,clog,storage,gin,以及standby 记录,仅举几例)。

XLOG记录向后链接。这样,每个入口指向文件中前面的条目。通过这种方式,我们可以完全相信,只要我们要到指向前一个条目的指针,我们就已经找到了记录的结尾。

使XLOG具有确定性

正如您所看到的,一个改变可以触发许多XLOG条目。对所有种类的语句来说,这都是真的;例如一个大的DELETE语句可以很容易造成上百万的变化。其原因是PostgreSQL不能简单地把SQL本身写入日志;它必须真实记录对表所做的物理改变。这是为什么?考虑一下下面的例子:

test=# DELETE FROM t_test WHERE id > random();

DELETE 5335

函数random每次被调用时,都产生不同的输出,因此,我们不能仅仅把SQL写入日志,因为如果在重放期间它被执行,这不能保证给我们提供相同的结果。

使XLOG可靠

在整个数据库实例中,XLOG本身是最关键和最敏感的部分之一。因此,我们必须采取特殊照顾,以确保做所有可能的事情来保护它。在崩溃的情况下,如果没有XLOG,数据库实例通常会遭遇不幸。

在内部,PostgreSQL采取特殊的预防措施来处理XLOG:

• 使用 CRC32 校验和

• 禁用信号

• 空间分配

首选,每条XLOG记录包含一个CRC32校验和。这允许我们检查日志在启动时的完整性。崩溃之前的最后一次写操作完全没有消息是完全可行的,   因此,一个校验和绝对有助于解决这个问题。校验和由PostgreSQL自动计算,并且用户没有必要关心这个明确的功能。

除了校验和,当写XLOG时,PostgreSQL将暂时禁用信号。这给了安全一些额外的级别,并在某种程度上降低了愚蠢的极端情况的可能性。

最后,PostgreSQL使用一个固定大小的XLOG。XLOG的大小由检查点段以及checkpoint_completion_target确定。

PostgreSQL事务日志大小的计算方法如下:

checkpoint_segments + wal_keep_segments + 1 files

重要的是,如果某个东西的大小是固定的,它很少用尽空间。

[在基于事务日志复制的情况下,如果事务日志无法存档,我们可以用尽XLOG目录的空间。]

您可以在下一个章节了解这个主题更多的内容。

2.5.2 LSN和共享缓冲区的交互

如果您要修复一个表,您必须确保按照正确的顺序修复表;如果一行数据在它实际产生之前被删除,这将是一场灾难。因此XLOG为您提供了所有改变的顺序。在内部,通过逻辑序列号(LSN)来反映这个顺序。对XLOG来说LSN是必不可少的。每个XLOG条目将被直接分配给一个LSN。

在前面的一个章节,我们已经讨论了一致性级别。synchronous_commit设置为off,即便XLOG记录还没有被刷新到磁盘,客户端也会获得一个OK。因为更改必须在高速缓存中反映,并且由于写XLOG必须在写数据表之前完成,系统必须确保并不是在共享缓存中的所有块都可以被立即写出来。LSN会保证,如果相应的变化已经写到了XLOG,我们只能从共享缓存把数据块写到数据文件。写入XLOG是根本,在崩溃后,违反了这个规则肯定会导致问题。

调试XLOG并把它们放在一起

既然我们已经知道了XLOG的基本工作原理,我们就可以把它们放在一起并研究一下XLOG。到了PostgreSQL9.2,工作原理如下:我们要从源代码编译PostgreSQL。在我们这样做之前,我们应该修改位于src/include/pg_config_manual.h的文件。在大约250行,我们可以取消WAL_DEBUG的注释并正常编译。这将允许我们设置一个称为wal_debug的客户端变量:

test=# SET client_min_messages TO log;

SET

test=# SET wal_debug TO on;

SET

除此之外,我们要设置client_min_messages,以确保日志消息会到达我们的客户端。

我们为我们的测试使用下面的表结构:
test=# \d t_test

Table "public.t_test"

Column | Type | Modifiers

--------+---------+-----------

id | integer |

name | text |

Indexes:

"idx_id"btree (id)

"idx_name"btree (name)

如果PostgreSQL已经正常编译(只有这样),我们将在屏幕上看到关于XLOG的信息:

test=# INSERT INTO t_test VALUES (1, ‘hans‘);

LOG: INSERT @ 0/17C4680: prev 0/17C4620; xid 1009; len 36: Heap -

insert(init): rel 1663/16384/16394; tid 0/1

LOG: INSERT @ 0/17C46C8: prev 0/17C4680; xid 1009; len 20: Btree

- newroot: rel 1663/16384/16397; root 1 lev 0

LOG: INSERT @ 0/17C4700: prev 0/17C46C8; xid 1009; len 34: Btree

- insert: rel 1663/16384/16397; tid 1/1

LOG: INSERT @ 0/17C4748: prev 0/17C4700; xid 1009; len 20: Btree

- newroot: rel 1663/16384/16398; root 1 lev 0

LOG: INSERT @ 0/17C4780: prev 0/17C4748; xid 1009; len 34: Btree

- insert: rel 1663/16384/16398; tid 1/1

LOG: INSERT @ 0/17C47C8: prev 0/17C4780; xid 1009; len 12:

Transaction - commit: 2013-02-25 18:20:46.633599+01

LOG: XLOG flush request 0/17C47F8; write 0/0; flush 0/0

正如本章所述,PostgreSQL将先向表本身(heap)添加一行。然后XLOG包含所有与索引相关的条目。最后,添加一个提交记录。

总之,156字节已经能够成功写入XLOG;这远远超过了我们实际添加的数据。一致性,性能(各项指标)和可靠性都配备了价格标签。

2.6 总结

本章,您已经了解了PostgreSQL的事物日志的目的。我们已经广泛地讨论的磁盘上的数据格式和一些非常重要的主题,例如:一致性和性能。在下一章中,我们复制我们的第一个数据库时就会需要所有这些主题。

下一章将建立在您刚才学到的主题之上,重点关注即时恢复。目标是使PostgreSQL及时恢复到一个特定的时间点并提供好像后面的事务从来没有发生过的数据。

原文地址:http://www.cnblogs.com/songyuejie/p/4743344.html

原文地址:http://www.cnblogs.com/songyuejie/p/4743344.html

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(5)

标签:

原文地址:http://www.cnblogs.com/songyuejie/p/4743344.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!