全文:
PostgreSQL中刷shared buffer的试验
作者:osdba 发布于:2012-5-14 16:07 Monday 分类:PostgreSQL
在Oracle数据库中,使用alter system flush buffer_cache;就可以把cache住的数据块从内存中刷出去,于是想在PostgreSQL库中如何实现这个功能呢。查看源代码,发现了两个函数 DropRelFileNodeBuffers和DropDatabaseBuffers的类似的功能。于是照葫芦画瓢用写了一个模块flushbuffer(源码见附件),实现了这个功能,下面演示一下:
postgres=# CREATE EXTENSION flushbuffer;
CREATE EXTENSION
postgres=#
建两个测试表tang01、tang02:
postgres=# create table tang01(id int,name text);
CREATE TABLE
postgres=# create table tang02(id int,name text);
CREATE TABLE
postgres=# insert into tang01 select generate_series(1,1000),'aaaaaaaaaaaaaaaa';
INSERT 0 1000
postgres=# insert into tang02 select generate_series(1,1000),'bbbbbbbbbbbbbbbb';
INSERT 0 1000
使用checkpoint把脏数据都保存到数据文件中:
postgres=# checkpoint;
CHECKPOINT
postgres=# select oid,relname,relfilenode from pg_class where relname like 'tang0%';\
oid | relname | relfilenode
-------+---------+-------------
16409 | tang01 | 16409
16415 | tang02 | 16415
查询两个表:
postgres=# select * from tang01 limit 10;
id | name
----+------------------
1 | aaaaaaaaaaaaaaaa
2 | aaaaaaaaaaaaaaaa
3 | aaaaaaaaaaaaaaaa
4 | aaaaaaaaaaaaaaaa
5 | aaaaaaaaaaaaaaaa
6 | aaaaaaaaaaaaaaaa
7 | aaaaaaaaaaaaaaaa
8 | aaaaaaaaaaaaaaaa
9 | aaaaaaaaaaaaaaaa
10 | aaaaaaaaaaaaaaaa
(10 rows)
postgres=# select * from tang02 limit 10;
id | name
----+------------------
1 | bbbbbbbbbbbbbbbb
2 | bbbbbbbbbbbbbbbb
3 | bbbbbbbbbbbbbbbb
4 | bbbbbbbbbbbbbbbb
5 | bbbbbbbbbbbbbbbb
6 | bbbbbbbbbbbbbbbb
7 | bbbbbbbbbbbbbbbb
8 | bbbbbbbbbbbbbbbb
9 | bbbbbbbbbbbbbbbb
10 | bbbbbbbbbbbbbbbb
(10 rows)
这时把tang02的数据文件直接覆盖tang01的数据文件:
osdba@osdba-laptop:/data/pgdata/base/11955$ ls -l 16415
-rw------- 1 osdba osdba 57344 5月 14 16:18 16415
osdba@osdba-laptop:/data/pgdata/base/11955$ ls -l 16409
-rw------- 1 osdba osdba 57344 5月 14 16:18 16409
osdba@osdba-laptop:/data/pgdata/base/11955$ cp 16415 16409
继续查询tang01:
postgres=# select * from tang01 limit 10;
id | name
----+------------------
1 | aaaaaaaaaaaaaaaa
2 | aaaaaaaaaaaaaaaa
3 | aaaaaaaaaaaaaaaa
4 | aaaaaaaaaaaaaaaa
5 | aaaaaaaaaaaaaaaa
6 | aaaaaaaaaaaaaaaa
7 | aaaaaaaaaaaaaaaa
8 | aaaaaaaaaaaaaaaa
9 | aaaaaaaaaaaaaaaa
10 | aaaaaaaaaaaaaaaa
发现看到的还是旧数据,原因是在内存中cache了表tang01的数据块,虽然tang01的底层的数据文件16409的内容变成了16415,但内存中的内容还没有变过来。
使用我写的flushtable函数把share buffer刷出去:
postgres=# select oid,* from pg_tablespace;
oid | spcname | spcowner | spclocation | spcacl | spcoptions
------+------------+----------+-------------+--------+------------
1663 | pg_default | 10 | | |
1664 | pg_global | 10 | | |
(2 rows)
postgres=# select oid,datname from pg_database;
oid | datname
-------+-----------
1 | template1
11947 | template0
11955 | postgres
(3 rows)
postgres=# select flushtable(1663,11955,16409);
flushtable
------------
9
(1 row)
再查询tang01,发现内容已经变成与tang02一样的:
postgres=# select * from tang01 limit 10;
id | name
----+------------------
1 | bbbbbbbbbbbbbbbb
2 | bbbbbbbbbbbbbbbb
3 | bbbbbbbbbbbbbbbb
4 | bbbbbbbbbbbbbbbb
5 | bbbbbbbbbbbbbbbb
6 | bbbbbbbbbbbbbbbb
7 | bbbbbbbbbbbbbbbb
8 | bbbbbbbbbbbbbbbb
9 | bbbbbbbbbbbbbbbb
10 | bbbbbbbbbbbbbbbb
注意:
我写的这个flushtable函数,只是简单把内存中的数据块丢弃掉,如果数据块是脏块,就会造成数据丢失,请大家不要在生产库使用这个模块,这个模块仅做为研究PostgreSQL源代码使用。
此包的使用方法:
把此包解压下PostgreSQL9.1.3源代码中的contrib目录下,进个flushbuffer目录下:
make && make install即可
flushbuffer下载