公开了bbsdown的源代码下载

下载地址:http://www.54chen.com/bbsdown

一个小工具,在学校的bbs里,许多时候限制上传2m大小的东西,如果要传大的附件的时候,都会分卷压缩了才上传,这样,一个页面里有很多的需要下载的东西,有多少个分卷就要点多少次下载。

此工具就是解决这个问题,方便下载一个帖子里的所有分卷压缩包,只需要指定一个帖子的起始和结束页面地址,再加上压缩包的名字,bbsdown就可以自己在后台全部下载在指定的目录内。

当Pg连接数达到一定数量时,Pgsql进程会终止,报Out of Memory

Q: 当Pg连接数达到一定数量时,Pgsql进程会终止,报Out of memory
A:在 Linux 2.4 以及之后的版本里,缺省的虚拟内存的设置对于 PgSQL而言不是最优的(32M)。原因也可能在于内核实现内存提交的方法导致出现了“过提交”内存(具体情况由于没有遇到,不作评述),如果其它进程的内存请求导致系统用光虚拟内存,那么内核可能会立即终止 PGSQL 服务器进程并会出具Out of memory报错,唯一的解救方法只能手工kill掉数据库进程,重启数据库。修改方法为:

sysctl -w kernel.shmmax=134217728
sysctl -w kernel.shmall=2097152
sysctl -w vm.overcommit_memory=2
或者直接echo进proc中去(我个人喜欢比较传统的操作)
echo 134217728 >/proc/sys/kernel/shmmax
echo 2097152 >/proc/sys/kernel/shmall
echo 2 > /proc/sys/vm/overcommit_memory
考虑到并不是每个人都乐意于每次开机都作此操作,最好还是修改/etc/sysctl.config文件添加相应的设置。

Slony不同步数据?

Q:配置了Slony,并未报错,但数据没同步过来
A:你要同步的表都设置主键了么,如果没有设主键的Slony配置表的属性的时候要加Serial属性哦

Slony同步数据非常慢?

Q:Slony同步数据非常慢,需要20~30s,且配置Slony的机器上cpu消耗严重?
A:检查slony同步的时间间隔,默认是10000微妙,这个数值还不错,别设置太低了。

使用plproxy和pgbouncer完成分布式处理

 

plproxy和pgbouncer都是skype开发的基于postgresql的开源应用;前者主要用于完成分布式计算,后者主要充当数据库连接池;它们的主页在[plproxy]和[pgbouncer

plproxy的特性

 

  • 使用plproxy类似于RPC;假设我们有A,B两台数据库,在A在创建一个plproxy的function,并指定一些参数和返回值,就可以在B上也创建一个同名的pgsql函数,并指定同样的参数和返回值;这样,在A上调用该function,通过适当地声明,就可以实现在B上调用该函数的同样效果,但结果是在A上返回的;
  • plproxy还能合并多个结点服务器上返回的结果集,就像是这些结果是由一个函数产生的一样,方便客户端操作;
  • plproxy可以指定同时在所有结点服务器上执行操作,或者只在指定的几台服务器上操作,或者只在任意一台结点服务器上执行操作;
  • plproxy默认是自动提交的;也就是说,只要目标服务器的函数执行成功了,它就会提交;这样有可能造成各个结点数据库的状态并不一致;因为可能有的结点执行成功了,有的没有执行成功,但plproxy并不会因为一个结点失败就回滚其它结点的操作
  • 一开始,我们只有一台账户数据库;但随着账户增加,单个数据库肯定满足不了需求;当多台数据库服务器并存的情况下,需要解决负载平衡的问题;

    为此,我们在系统的syshostconfig表中存储了一个key为accountNum,value为整数的参数;每次进行开户操作时,先用plproxy在所有数据库上查出该值并返到proxy层;由pgsql函数找出哪个数据库的accountNum最小,然后就在该数据库上开户,并将对应的accountNum加1

    这样,新增服务器将立即开始承担新用户的注册;原有服务器压力不变; 

    plproxy中的死锁

    考虑两个账户a@a.com和b@b.com,如果出现a@a.com向b@b.com转账,恰好b@b.com也在向a@a.com转账,就会出现死锁的情况;即一个进程已经拿到a@a.com的锁,并等待b@b.com,而另一个进程拿到了b@b.com的锁,并等待a@a.com;

    一个可行的解决办法就是所有操作都按照一个可以预见的顺序进行;也就是限制转账操作的交易顺序,通过对交易双方的账号进行排序是一个较为简单的办法;

    针对以上问题,如果我们限制对a@a.com的操作,无论是付款还是收款都优先操作,而b@b.com永远都排在它后面,也就解决了死锁的问题;

    因此,在转账交易中,首要任务是对账户名进行排序;至于先收款还先付款,其实不重要

    PostgreSQL系统安装(Linux)

  • 1. 到 http://www.postgresql.org下载pg8.2.4 source
  • 2. 编译安装pgsql
    • tar xvfj postgresql-8.2.4.tar.bz2
    • cd postgresql-8.2.4
    • ./configure --prefix=/home/y/pgsql #注意下一步把这个目录加入你bash的PATH中去
    • gmake
    • sudo gmake install
    • sudo mkdir /home/y/pgsql/data
    • sudo chown yahoo /home/y/pgsql/data
    • sudo -u yahoo /home/y/pgsql/bin/initdb --locale=zh_CN.UTF-8 --encoding=utf8 -D /home/y/pgsql/data
  • 3.创建数据库
    • cd /home/y/pgsql/bin
    • sudo -u yahoo ./pg_ctl start -D /home/y/pgsql/data #启动服务进程
    • sudo -u yahoo /home/y/pgsql/bin/createdb test #创建数据库test
    • sudo -u yahoo /home/y/pgsql/bin/psql test
    • test=# create role changxin superuser login ;
    • test=# \q
    • 备注:现在就可以直接登入test数据库进行操作了。并且我的权限是最大权限的superuser。 
  • Plproxy部署手册

    安装过程如下:
    1 安装plproxy:下载plproxy.安装完成plproxy后,运行{$PATH_TO_PG}/share/contrib/plproxy.sql
    2 建立数据库_proxy;
    3 建立plpgsql语言;
    4 在_proxy中建立模式plproxy;分配权限 grant all on schema plproxy to <用户>。
    5 建立pgcluster; 
     --以上步骤sql语句:
     CREATE FUNCTION plpgsql_call_handler () RETURNS language_handler AS
         '/usr/local/pgsql/lib/plpgsql.so'  LANGUAGE C;

    CREATE FUNCTION plpgsql_validator(oid) RETURNS void AS
    '/usr/local/pgsql/lib/plpgsql.so' LANGUAGE C;

    CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql'
    HANDLER plpgsql_call_handler
    VALIDATOR plpgsql_validator;

    --------------------------------------------------------------------

    drop schema if exists plproxy cascade;

    create schema plproxy;

    grant all on schema plproxy to yahoo;

    --------------------------------------------------------------------
    create or replace function plproxy.get_cluster_version(cluster_name text)

    returns integer as $$

    begin
    if cluster_name = '<cluster名字>' then

    return 8;

    end if;

    raise exception 'no such cluster: %', cluster_name;

    end; $$ language plpgsql;

    --------------------------------------------------------------------
    create or replace function plproxy.get_cluster_partitions(cluster_name text)

    returns setof text as $$

    begin

    if cluster_name = '<cluster名字>' then

    --return next 'host=202.165.97.144 port=6000 user=chry password=chry dbname=chry_134';

    return next 'host=pg1.sns.cn3.yahoo.com user=yahoo dbname=sns_search';
    return next 'host=pg2.sns.cn3.yahoo.com user=yahoo dbname=sns_search';

    return;

    end if;

    raise exception 'no such cluster: %', cluster_name;

    end; $$ language plpgsql;

    --------------------------------------------------------------------
    create or replace function plproxy.get_cluster_config(cluster_name text, out key text, out val text)

    returns setof record as $$

    begin

    key := 'statement_timeout';

    val := 60;

    return next;

    return;

    end; $$ language plpgsql;

    6 建立查询函数
     --在_proxy中建立查询函数:
     CREATE OR REPLACE FUNCTION public.doquery(query text)
     RETURNS setof record AS $$
     CLUSTER '<cluster名字>';
     RUN ON ALL;
     $$ LANGUAGE plproxy;

    --------------------------------------------------------------------
    CREATE OR REPLACE FUNCTION public.doquery(urlstr text,query text)
    RETURNS setof record AS $$
    CLUSTER '<cluster名字>';
    RUN ON hashtext(urlstr);
    $$ LANGUAGE plproxy;

    --------------------------------------------------------------------
    CREATE OR REPLACE FUNCTION public.dmlExec(query text)
    RETURNS integer AS $$
    CLUSTER '<cluster名字>';
    RUN ON ALL;
    $$ LANGUAGE plproxy;

    --------------------------------------------------------------------
    CREATE OR REPLACE FUNCTION public.dmlExec(urlstr text,query text)
    RETURNS integer AS $$
    CLUSTER '<cluster名字>';
    RUN ON hashtext(urlstr);
    $$ LANGUAGE plproxy;  

     --在所联邦的数据库中建立查询函数:
     CREATE OR REPLACE FUNCTION public.doquery(query text)
     RETURNS SETOF RECORD AS $$
     DECLARE
     row RECORD;
     BEGIN
     for row in execute query loop
     return next row;
     end loop;
     return;
     END;
     $$ LANGUAGE plpgsql;

    ----------------------------------------------------------------
    CREATE OR REPLACE FUNCTION public.doquery(urlstr text,query text)
    RETURNS SETOF RECORD AS $$
    DECLARE
    row RECORD;
    BEGIN
    for row in execute query loop
    return next row;
    end loop;
    return;
    END;
    $$ LANGUAGE plpgsql;

    ----------------------------------------------------

    CREATE OR REPLACE FUNCTION public.dmlExec(query text)
    RETURNS integer AS $$
    DECLARE
    ret integer;
    BEGIN
    execute query;

    GET DIAGNOSTICS ret = ROW_COUNT;
    RETURN ret;

    END;
    $$ LANGUAGE plpgsql;

    ---------------------------------------------------------------
    CREATE OR REPLACE FUNCTION public.dmlExec(urlstr text,query text)
    RETURNS integer AS $$
    DECLARE
    ret integer;
    BEGIN
    execute query;

    GET DIAGNOSTICS ret = ROW_COUNT;
    RETURN ret;

    END;
    $$ LANGUAGE plpgsql;

    Pgsql如何控制来自其他电脑的连接?

    • 缺省情况下,PostgreSQL只允许来自本机且通过 unix 域套接字或TCP/IP方式的连接。你只有在修改了配置文件postgresql.conf中的listen_addresses,且也在配置文件$PGDATA/pg_hba.conf中打开了 基于远程电脑( host-based )的身份认证,并重新启动PostgreSQL,否则其他电脑是不能与你的PostgreSQL服务器进行连接的。
    • 将postgresql.conf中的listen_addresses设为:listen_addresses = '*'
    • 在pg_hba.conf中加入访问数据库的服务器的IP。如,IP=10.62.130.136,在pg_hba.conf的最后加入 host all all 10.62.130.136/32 trust

    Pgpool安装

    下载地址:http://pgfoundry.org/projects/pgpool/
    文件为:pgpool-II-2.0.1.tar,tar xvfj pgpool-II-2.0.1.tar
    在pgpool-II-2.0.1目录下,执行./configure --prefix=/home/y/share/pgsql ----with-pgsql=/home/y/share/pgsql,
    要求with-pgsql目录必须为pgsql安装目录。
    之后执行gmake,sudo gmake install;
    pgpool需要用PCP命令来连接数据库检索数据,其用户名、密码是在pcp.conf文件中保存的。密码是经过md5加密的,需要用户手工输入。
    cp /home/y/share/pgsql/etc/pcp.conf.sample /home/y/share/pgsql/etc/pcp.conf
    md5加密码可以用/home/y/share/pgsql/bin/pg_md5直接生成 :例/home/y/share/pgsql/bin/pg_md5 postgres 
    结果为e8a48653851e28c69d0506508fb27fc5
    将用户名,密码记入到pcp.conf文件中。
    pcp默认端口为pcp_port = 9898。可以在pgpool.conf文件内修改
    cp /home/y/share/pgsql/etc/pgpool.conf.sample /home/y/share/pgsql/etc/pgpool.conf,默认连接端口为port = 9999,
    默认只允许本地连接,listen_addresses = 'localhost',
    如果需要所有ip可连接,可改为listen_addresses = '*'。
    cp /home/y/share/pgsql/etc/pool_hba.conf.sample /home/y/share/pgsql/etc/pool_hba.conf,

    添加远端连接 host all all 0.0.0.0/0 trust.

    添加pgsql节点
    backend_hostname0 = 'phx6.sds.cnb.yahoo.com'
    backend_port0 = 5432
    backend_weight0 = 1
    backend_hostname1 = 'phx7.sds.cnb.yahoo.com'
    backend_port1 = 5432
    backend_weight1 = 1

    如果需要开启多级拷贝功能需要设置replication_mode = true
    如果需要开启负载均衡功能需要设置load_balance_mode = true

    启动pgpool
    pgpool -n -d > /tmp/pgpool.log 2>&1 &
    关闭pgpool
    pgpool stop