PostgreSQL 9.1 流式复制问题:replica 无法正确使用索引

Ale*_*lex 6 postgresql replication postgresql-9.1

我们在主服务器上的 Ubuntu Linux 12.04 上使用 PostgreSQL 9.1.7,在副本服务器上的 FreeBSD 9.0-RELEASE 上使用 PostgreSQL 9.1.7。副本服务器和主服务器对同一 SQL 查询返回不同的结果。查询计划显示使用索引(BTree 索引,我们根本不使用哈希索引)来获取结果,因此看起来索引在副本服务器上处于不一致或不完整状态。主服务器上的查询:

db1=# select id from users where email='xxxx@xxxx.net';
   id    
---------
 1698116
(1 row)

db1=#
Run Code Online (Sandbox Code Playgroud)

在副本服务器上的查询:

db1=> select id from users where email='xxxx@xxxx.net';
 id 
----
(0 rows)

db1=> select created_at from users where id=1698116;
         created_at         
----------------------------
 2013-03-04 10:40:05.221214
(1 row)

db1=>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,副本数据库已经包含一个具有正确 ID 的用户,因此数据已就位,但由于某种原因尚未编入索引。我们仔细检查了副本是否处于接收/重新应用状态,因此这不是暂时中断。用户从未被编入索引。我们也曾在 CentOS 5.6 上使用 PostgreSQL 9.0 遇到过类似问题,因此我们认为这不是 FreeBSD 或 PostgreSQL 9.1 特定的问题。

我们使用副本服务器运行大量繁重的 SQL 查询,这可能是问题的根源吗?无论如何,我们如何才能有效地检测和防止将来发生此类情况?副本今天没有停机,日志中没有任何错误行,所以我们只是偶尔检测到这种不一致。

Dan*_*ité 5

假设数据库的语言环境en_GB.UTF-8在 Ubuntu(主)和 FreeBSD(从)中,我相信排序语义的差异可能会导致索引在从上无法使用的事实。

以下是它们如何以不同方式排序的示例:

在 Ubuntu 12.04 上:

$ export LANG=en_GB.UTF-8
$ cat >file
"0102"
0102 
$ sort file
0102
"0102"
Run Code Online (Sandbox Code Playgroud)

在 FreeBSD 9.0-RELEASE 上:

$ export LANG=en_GB.UTF-8
$ cat >file
"0102"
0102
$ sort file
"0102"
0102
Run Code Online (Sandbox Code Playgroud)

这给出了同一区域不同的订单两个字符串"0102"0102(即使他们甚至不包含US-ASCII字符集以外的任何字符...)

这是我建议您在自己的数据集上尝试的测试:

在主人身上:

$ psql -d dbname -Atc 'select email from users' | LC_COLLATE=en_GB.UTF-8 >email.master
Run Code Online (Sandbox Code Playgroud)

在奴隶上:

$ psql -d dbname -Atc 'select email from users' | LC_COLLATE=en_GB.UTF-8 >email.slave
Run Code Online (Sandbox Code Playgroud)

现在比较email.masteremail.slave与差异或CMP。我怀疑你会发现它们并不相同。在这种情况下,它表明不能使用索引副本,因为它在主服务器上的构建规则与从服务器上的扫描规则不同。