- 本文地址: https://www.laruence.com/2009/06/09/912.html
- 转载请注明出处
不知道"拉"一天开始, 好像大家都开始谈论PgSQL了, 呵呵, 最近尝试在项目中使用Pgsql, 现在就将使用Slony-I配置PostgreSQL同步的过程拿来与大家分享.
话说Pgsql虽然很流行,但是国内的文档真的是很少,尤其配置同步这块,基本上都是互相转贴, 写的也很笼统,在我自己配置过程中, 遇到了很多问题. 本文将努力将各种概念解释清楚, 尽量避免大家再遇到我遇到的疑难问题.
Slony-I是一个BSD授权的开源项目, 致力于解决Pgsql的同步.
它通过在配置中指明的数据库中的特定表上增加trigger(触发器), 从而在主库有变更的时候, 通过trigger函数连接到各个要同步的从库上同步从库.
正因为如此, 所以我们需要首先创建在每个数据库上的用户, 并且为超级用户, 并且需要配置pg_hab.conf使得主库和从库之间可以互联.
创建用户可以简单的使用pgsql的createuser, 以下我们假设创建的超级用户为repl,密码也为repl
$ pgsql_dir/bin/createuser -p repl
另外, 由于Slony的触发器函数是PLPGSQL语言写的, 所以我们也要给相应的数据库安装相应的语言包.
$ pgsql_dir/bin/createlang -d dbname plpgsql
接下来, 必须在主服务器和从服务器上都下载编译安装 slony-i(我的配置中, slony安装在/home/work/local/slony下, 请根据情况调整相关参数).
首先我们配置主服务器上:
1. 在主服务器上, 我们编辑一个shell脚本:configMaster.
#!/bin/sh SLONIK=/home/work/local/slony/bin/slonik #slonik可执行文件位置 CLUSTER=Laruence #自定定义你的集群(Cluster)的名称 MASTER_ID=1 #主库ID MASTER_HOST=db1.laruence.com #主库IP或主机名 MASTER_DBNAME=ams #需要复制的数据库名字 MASTER_USER=repl #主库数据库超级用户名 MASTER_PASSWORD=repl #主库数据库超级用户密码 SLAVER_ID=2 #从库ID SLAVER_HOST=db2.laruence.com #从库IP或主机名 SLAVER_DBNAME=ams #需要同步的数据库名字(可以和主库数据库的名字不同) SLAVER_USER=repl #从库数据库超级用户名 SLAVER_PASSWORD=repl #从库数据库超级用户密码 $SLONIK<<_EOF_ cluster name = $CLUSTER; #指明要定义的Cluster名 node $MASTER_ID admin conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD'; node $SLAVER_ID admin conninfo = 'dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$SLAVER_USER password=$SLAVER_PASSWORD'; init cluster(id = 1, comment = 'Primary Cluster'); #初始化Cluster,ID从1开始 create set ( id = 1, origin = $MASTER_ID, comment = 'Data Provider' ); #定义复制集, origin指明主库 set add table ( set id = 1, origin = $MASTER_ID, id = 1, fully qualified name = 'public.repl', comment='Repl Table' ); #为复制集合中增加表, fully qualified name 指明了要复制的表名. store node ( id = $SLAVER_ID, comment = 'Slave Node', event node=$MASTER_ID); #定义从库节点 #定义路由路径 store path ( server=1, client=2, conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD'); #添加事件监听 store listen ( origin = $MASTER_ID, provider = $MASTER_ID, receiver = $SLAVER_ID ); _EOF_
然后赋予这个脚本可执行权限, 并在主库服务器上执行这个脚本.
如果执行成功, 我们在$MASTER_DBNAME的数据库中, 查看响应的表的话, 会发现, 这个表被增加了俩个触发器函数:
ams=# \d repl Table "public.repl" Column | Type | Modifiers ----------+------------------------+--------------------------------------------------- id | integer | not null default nextval('repl_id_seq'::regclass) username | character varying(100) | Indexes: "repl_pkey" PRIMARY KEY, btree (id) Triggers: "_Laruence_logtrigger" AFTER INSERT OR DELETE OR UPDATE ON repl FOR EACH ROW EXECUTE PROCEDURE "_Laruence".logtrigger('_Laruence', '1', 'k') Disabled triggers: "_Laruence_denyaccess" BEFORE INSERT OR DELETE OR UPDATE ON repl FOR EACH ROW EXECUTE PROCEDURE "_Laruence".denyaccess('_Laruence')
详细信息, 大家也可以在pg_proc, pg_namespace寻找到更多信息.
2. 然后分别在主库服务器和从库服务器上启动slon进程, 开始监听.
主库服务器上: ./slon Laruence "dbname=ams host=slaver_host user=repl password=repl port=5432" & //其中Laruence为你定义的Cluster名
从库服务器上: ./slon Laruence "dbname=ams host=slaver_host user=repl password=repl port=5432"& //其中Laruence为你定义的Cluster名
3. 接下来,在主库服务器上提交同步集, 同样的建立一个shell脚本
#!/bin/bash SLONIK=/home/work/local/slony/bin/slonik #slonik可执行文件位置 CLUSTER=Laruence #自定定义你的集群(Cluster)的名称 MASTER_ID=1 #主库ID MASTER_HOST=db1.laruence.com #主库IP或主机名 MASTER_DBNAME=ams #需要复制的数据库名字 MASTER_USER=repl #主库数据库超级用户名 MASTER_PASSWORD=repl #主库数据库超级用户密码 SLAVER_ID=2 #从库ID SLAVER_HOST=db2.laruence.com #从库IP或主机名 SLAVER_DBNAME=ams #需要同步的数据库名字(可以和主库数据库的名字不同) SLAVER_USER=repl #从库数据库超级用户名 SLAVER_PASSWORD=repl #从库数据库超级用户密码 $SLONIK<<_EOF_ cluster name = $CLUSTER; #指明要定义的Cluster名 node $MASTER_ID admin conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD'; node $SLAVER_ID admin conninfo = 'dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$SLAVER_USER password=$SLAVER_PASSWORD'; # 提交订阅复制集 subscribe set ( id=1, provider=$MASTER_ID, receiver=$SLAVER_ID, forward=no); _EOF_
同样,赋予这个脚本执行权限, 执行既可.
现在看看是否已经开始同步了呢?
Q&A:
1. 提示db_getLocalNodeId() wrong database?
检查store path是否设置正确, 主从是否指向正确.
2. 提示duplicate key sl_nodelock-pkey and duplicate ...?
检查主机和从机上的slon进程都是连接向对方, 不要重复.
3. 运行configmain的时候, 提示REQUIRE EVENT NODE?
在定义store node 的时候, 需要指明事件源节点, 在本例中是主机节点($MASTER_ID)
4. 提示cannot connect to local database - fe_sendauth: no password supplied:
这是因为slony使用的c pgsql lib需要你在用户根目录下建立一个.pgpass文件, 文件的属性必须为0600, 文件的内容格式为: hostname:port:database:username:passwor, 前4个字段,都可以使用"*"通配.
5. 能否实现主从互相同步呢?
可以, 只要指明反向的store path, 在订阅集中指明对映的复制条目, 既可.
6. 能否实现多个从机呢?
可以, 添加多个node, store path, set条目既可.
7. 还有其他问题,怎么办?
访问我的blog留言交流.
参考文档: SLONY-I
コーチのお財布でレザーは、あまり見た事がなくて、一目惚れでした!3つ折り財布は持った事がないですが、カードもたくさん入って使い易いです。商品説明に詳しく書かれていたので、安心して買う事ができました。
配送も早くて、しかも手書きのお手紙には感動です。何度か買い物しましたが、今までのショップの中で一番のお店です。
また、機会がありましたら、よろしくお願いしますm(__)m
大満足です!!
ありがとうございます
コーチ コーチ★レザー 3つ折り長財布★カーフ★朱色★
大満足!!
画素通りで、とっても可愛いし、状態もいいです。迅速な対応と、手書きのお手紙、ありがとうございました。またの機会に、よろしくお願いしますm(__)m
スーパーコピー クロムハーツ 財布 一生もの https://www.gmt78.com/product/detail/11848.htm
[…] 7. 还有其他问题,怎么办? 访问我的blog留言交流. […]
大牛,怎么也不说一下是什么系统环境,什么版本啊!
和其它资料差不多,只能当文章看啊!
都说成功了,都不可复制!
原来是将$SLONIK写成#SLONIK了,现在脚本可以执行,但是提示:
:7: PGRES_FATAL_ERROR select “_Laruence”.determineIdxnameUnique(‘public.repl’, NULL); – ERROR: Slony-I: table “public”.”repl” not found
路径是对的:
# whereis slonik
slonik: /usr/bin/slonik
我的脚本是:
#!/bin/sh
SLONIK=/usr/bin/slonik
CLUSTER=slony_test
MASTER_ID=1
MASTER_HOST=10.155.50.51
MASTER_DBNAME=hhm
MASTER_USER=repl
MASTER_PASSWORD=repl
SLAVER_ID=2
SLAVER_HOST=10.155.50.52
SLAVER_DBNAME=hhm
SLAVER_USER=repl
SLAVER_PASSWORD=repl
#SLONIK<<_EOF_
cluster name = $CLUSTER
node $MASTER_ID admin conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MA
STER_USER password=$MASTER_PASSWORD';
node $SLAVER_ID admin conninfo = 'dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$
SLAVER_USER password=$SLAVER_PASSWORD';
init cluster (id = 1, comment = 'Primary Cluster');
create set (id = 1, origin = $MASTER_ID, comment = 'Data Provider');
set add table ( set id = 1,origin = $MASTER_ID, id = 1, fully qualified name = 'pu
blic.repl', comment='Repl Table');
store node ( id = $SLAVER_ID, comment = 'Slave Node', event node=$MASTER_ID);
store path ( server=1, client=2, conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HO
ST USER=$MASTER_USER password=$MASTER_PASSWORD');
store listen ( origin = $MASTER_ID, provider = $MASTER_ID, receiver = $SLAVER_ID);
_EOF_
@smallfish /home/work/local/slony/bin/slonik 路径对么?
首先感谢博主写的这篇文章,请教一下,您这篇文章是完整的吗?我怎么在执行第一个脚本configMaster的时候就出错:
./master.sh: line 15: cluster: command not found
./master.sh: line 16: node: command not found
./master.sh: line 17: node: command not found
./master.sh: line 19: syntax error near unexpected token `(‘
./master.sh: line 19: `init cluster (id = 1, comment = ‘Primary Cluster’);’
是不是别的地方还要设置?
I propose not to wait until you get enough cash to buy all you need! You can just get the credit loans or short term loan and feel comfortable
哈哈 兄弟也开始搞pgsql啦,来看看我的小原创两篇 使用postgreSQL+bamboo搭建比lucene方便N倍的全文搜索 分两部分 http://www.54chen.com/c/601
http://www.54chen.com/c/634
欢迎指点哈
@cc0cc 把你当成SPAM了…^_^
同步周期或某一DB网络中断怎么处理的?
如果这样,需要重新做一遍整个工作. 貌似也没什么更好的办法.
Thanks for posting, I’ll definitely be subscribing to your blog.