市面上有一些提供DaaS服务的厂商,例如heroKu,可能有上百万的数据库服务;
又比如提供PaaS平台的服务商,数据库也会有很多,同事这些数据库可能也是模板化的,这些厂商并不一定是为每个客户都新建一个数据库集群来满足数据库的需求。
很有可能是使用数据库或者schema来隔离不同用户的。
1. 例如将模板存储在模板数据库中,根据一个模板数据库创建新的数据库提供服务。
2. 有或者将模板存储在SQL文件中,使用SQL文件构建新的SCHEMA提供服务。
两种方式构建模板的差别
1. 数据库的方式隔离比较彻底,共用的资源较少。
可以实现存储的隔离。
可以实现connection的隔离。
可以实现auth的隔离。
可以实现权限的隔离。
但是数据库与数据库之间是无法直接访问的,需要的话通过DBLINK或者FDW插件,当然也可以应用层面跨库访问。
2. schema的方式,共用资源较多,可以同时操作不同的schema之间的对象,事务都是本地事务。
简单来说是有schema更便捷,但是权限隔离没有使用数据库那么彻底,可以从pg_class等系统表窥探到没有权限的对象的定义。
从生成效率来讲,使用数据库模板的方式会高很多,因为它只需要COPY DIR,产生的REDO很少,也不需要大量的变更元数据。
从删除效率来讲,差别也非常大,删除SCHEMA与创建schema一样,会产生大量的REDO,甚至会导致STANDBY剧烈的延迟,后面会有分析。而删除数据库很快,只产生少量的REDO。
本文将要给大家分析的就是两者在创建和删除时的大幅差异。
用到两块PCI-E SSD,分别存放主库和备库。
主库监听5289,备库监听5290
1. postgresql.conf




进入template1数据库,准备schema。
\c template1 postgres主表建表语句如下,为了让schema尽量大一些,使用这种方法来建立。

…...

100个字段,每个字段都有一个约束。
在数据库元数据中,也会产生一大批系统记录,例如
每个表至少会新增的元数据(没算序列的,算序列还更多)
pg_class , 101条 (表+索引) pg_attribute , 106条 (tableoid, cmax, cmin, xmax, xmin, ctid, 字段) pg_constraint , 200条 (唯一, check各100个) pg_depend , 401条 (表, 索引+唯一约束+check约束)(索引,唯一约束) pg_index , 100条 同时还会产生很多数据文件,每个索引,表都会有一个数据文件,如果算上fork(vm, fsm, init)的话,就更多了。
使用test新建500张一样的表,会产生较多的元数据变动,同时会产生一堆数据文件。
do language plpgsql $$ declare i int ;begin for i in 1..500 loop execute 'create table test'||i||' (like test including all)'; end loop;end;$$;建完表后,template1就变500多MB了。

postgres=# create database db0 with template template1;postgres=# select pg_current_xlog_location();-[ RECORD 1 ]------------+-----------pg_current_xlog_location | 1/7394D08\c db0 drop schema public cascade;等待drop schema结束,并记录当前XLOG位点(很长一段时间后稳定(autovacuum)结束)
db0=# select pg_current_xlog_location();-[ RECORD 1 ]------------+-----------pg_current_xlog_location | 1/168E6EA8在主库执行

发现备库apply卡在一个REDO REC上很久,如果接下来主库又产生了大量的REDO,那么备库的apply就会延迟严重。
主机REDO发送是没有延迟的,也就是说REDO已经在备机那里了,但是还没有被apply。
-[ RECORD 1 ]----+------------------------------pg_size_pretty | bytespg_size_pretty | bytespg_size_pretty | bytespg_size_pretty | 56 MB -- 出现apply延迟pid | 27375usesysid | 10usename | postgresapplication_name | walreceiverclient_addr | 127.0.0.1client_hostname | client_port | 53164backend_start | 2016-10-12 10:17:16.414473+08backend_xmin | 2030state | streamingsent_location | 1/168E6EA8write_location | 1/168E6EA8flush_location | 1/168E6EA8replay_location | 1/13151E28 -- 卡住sync_priority | sync_state | async备机apply延迟严重的话,另外一个问题就是备机的xlog会占用较大的空间。
使用pg_xlogdump分析被堵塞的redo rec的内容
pg_xlogdump -b 000000010000000100000013 000000010000000100000014 2>&1 |less搜索1/13151E28

备库apply卡住的地方,跟踪备库startup进程(用于recovery的进程)在干什么
strace -p $pid 一堆的unlink
还有很多查看一下template1下面有多少个文件,(200多个是系统自带的一些元表的数据文件)有50954多个文件。
unlink这些文件至少也要耗费10几分钟。
1. drop schema 产生了多少redo
本例的测试用例,约17MB的REDO。
2. 为什么drop schema会导致standby apply的延迟严重
大量的文件操作,导致了apply的延迟。
postgres=# select pg_current_xlog_location(); pg_current_xlog_location -------------------------- 1/168EE5F8(1 row)postgres=# create database db0 with template template1;postgres=# select pg_current_xlog_location(); pg_current_xlog_location -------------------------- 1/168F0640(1 row)postgres=# select pg_xlog_location_diff('1/168F0640', '1/168EE5F8');-[ RECORD 1 ]---------+-----pg_xlog_location_diff | 8264postgres=# drop database db0;DROP DATABASEpostgres=# select pg_current_xlog_location(); pg_current_xlog_location -------------------------- 1/168F20E0(1 row)postgres=# select pg_xlog_location_diff('1/168F20E0','1/168F0640');-[ RECORD 1 ]---------+-----pg_xlog_location_diff | 6816在主库执行


分析一下create 和 drop database产生的redo内容
pg_xlogdump -b 000000010000000100000016 000000010000000100000016 2>&1 |less分析从1/168EE5F8到1/168F20E0的内容全部如下


文件操作少了,比drop schema快多了。
create 和 drop schema的文件操作很多,是一个个文件进行的,而且都会记录在REDO中,如果schema中有很对对象并且有很多文件的话,会非常慢。
create 和 drop database产生的日志少,系统调用也更少。
schema不建议作为daas的模板环境频繁使用,建议使用database作为模板。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917105/viewspace-3135293/ ,如需转载,请注明出处,否则将追究法律责任。