症状: 在db shcema中我们制定uuid column上面有一个unique的constraint,但是在某些failure case中我们可以看到uuid中出现两个相同的value
id | uuid | hostname
1 | 44454C4C-3600-104E-8047-C3C04F364A31 | etc003478a-001
2 | 44454C4C-3800-1039-8037-B9C04F364A31 | etc003478a-002
3 | 44454C4C-4E00-104B-8037-C3C04F364A31 | etc003478a-003
4 | 44454C4C-4D00-104B-8037-C3C04F364A31 | etc003478a-004
5 | 44454C4C-3200-1047-8037-B8C04F364A31 | etc003478a-005
6 | 44454C4C-4300-1039-804C-C7C04F334831 | etc003478a-006
7 | 44454C4C-3100-104C-804C-C4C04F334831 | etc003478a-007
8 | 44454C4C-3000-1042-8039-B5C04F4B4831 | etc003478a-008 <------------------
11 | 44454C4C-3000-1042-8039-B5C04F4B4831 | etc003478a-008 <------------------
模拟这种failure case的步骤
[1] 因为uuid申明为unique,所以postgresql会把它当成是index一样的列来单独存储在一个单独的文件里,所以我们首先要定位这个文件
select relname, relfilenode from pg_class where relname like 'nodes%';
relname | relfilenode
nodes | 16999
nodes_id_seq | 17015
nodes_pkey | 40965
nodes_uuid_key | 40966 <----------- this value is often not equivalent on different system.
[2] 接着要定位你的数据库在文件系统里面所处的目录,这个在$PG_DATA/pg_database里面有记录
[3] 有了以上这两个信息,我们就找到了那个存储index的文件,比如说数据库的目录是16384,index文件名诗40966,那么index文件的绝对路径就是$PG_DATA/base/16384/40966,打开以后会看到如下东西:
0@(^@^@^@44454C4C-3000-1042-8039-B5C04F4B4831^@^@^@^@^L^@0@(^@^@^@44454C4C-3000-1042-8039
B5C04F4B4831^@^@^@^@^C^@0@(^@^@^@44454C4C-4E00-104B-8037-C3C04F364A31^@^@^@^@^B^@0@(^@^@^@44454C4C-4D00-104B
8037-C3C04F364A31^@^@^@^@^E^@0@(^@^@^@44454C4C-4300-1039-804C-C7C04F334831^@^@^@^@^F^@0@(^@^@^@44454C4C-3800-1039-8037
B9C04F364A31^@^@^@^@^H^@0@(^@^@^@44454C4C-3600-104E-8047-C3C04F364A31^@^@^@^@^G^@0@(^@^@^@44454C4C-3200-1042-8037
B8C04F364A31^@^@^@^@^D^@0@(^@^@^@44454C4C-3100-104C-804C-C4C04F334831^@^@^@^@ ^@0@(^@^@^@44454C4C-3000-1045-8039
B5C04F4B4831^@^@^@^@^@^@^@^@^@^@^@^@C^@^@^@
显然这些就是uuid字段的值,我们可以把"44454C4C-3200-1042-8037B8C04F364A31"改成"44454C4C-3200-2334-8037B8C04F364A31",保存退出
[4] 别忘了重启postgresql
[5] 在我们hack之前,先看一下table里面的东西,方便后面作一个比较
SELECT id, uuid, hostname from nodes order by id;
id | uuid | hostname
1 | 44454C4C-3600-104E-8047-C3C04F364A31 | etc003478a-001
2 | 44454C4C-3800-1039-8037-B9C04F364A31 | etc003478a-002
3 | 44454C4C-4E00-104B-8037-C3C04F364A31 | etc003478a-003
4 | 44454C4C-4D00-104B-8037-C3C04F364A31 | etc003478a-004
5 | 44454C4C-3200-1047-8037-B8C04F364A31 | etc003478a-005
6 | 44454C4C-4300-1039-804C-C7C04F334831 | etc003478a-006
7 | 44454C4C-3100-104C-804C-C4C04F334831 | etc003478a-007
8 | 44454C4C-3000-1042-8039-B5C04F4B4831 | etc003478a-008
[6] 我们在插入一个记录,这个记录的uuid 是已经存在的"44454C4C-3100-1042-804C-C4C04F334831".
INSERT INTO nodes(uuid, hostname) values('44454C4C-3000-1042-8039-B5C04F4B4831', 'etc003478a-008');
[7] "SELECT id, uuid, hostname from nodes order by id;"
id | uuid | hostname
1 | 44454C4C-3600-104E-8047-C3C04F364A31 | etc003478a-001
2 | 44454C4C-3800-1039-8037-B9C04F364A31 | etc003478a-002
3 | 44454C4C-4E00-104B-8037-C3C04F364A31 | etc003478a-003
4 | 44454C4C-4D00-104B-8037-C3C04F364A31 | etc003478a-004
5 | 44454C4C-3200-1047-8037-B8C04F364A31 | etc003478a-005
6 | 44454C4C-4300-1039-804C-C7C04F334831 | etc003478a-006
7 | 44454C4C-3100-104C-804C-C4C04F334831 | etc003478a-007
8 | 44454C4C-3000-1042-8039-B5C04F4B4831 | etc003478a-008
11 | 44454C4C-3000-1042-8039-B5C04F4B4831 | etc003478a-008 <--------------------
[8] 我们看到我们成功模拟了postgresql的index corruption现象。但是,别忘了,我们还不知道情况中这种现象是由什么导致的,还要继续学习 ...
阅读(583) | 评论(0) | 转发(0) |