postgresql 内核开发之系统参数增加(下)

上篇介绍了怎么加一个常规参数,同时也留下了一个问题,如何加一个奇葩参数设置功能,使任意一个session设置参数值,全局所有连接立即生效。
如何实现呢?我们来分析下。
如果要使当前session生效,直接设置即可,它能直接读写当前进程的参数值。那其它的session呢?首先我们明确一个问题,数据库一旦正常运行起来后,所有的动作都是在事务中进行的,如果一个连接session在等待任务中,其它连接session的一些语句动作是无法直接影响到处于等待连接的session的。但是不同连接session肯定是有相互影响的,比方说A session建个表,B session读写这个表,肯定是可以的,任何session中事务只要提交那么就对全局都可见,这是数据库的基础,比方说是在StartTransaction()函数中的AtStart_Cache()函数会根据主进程的消息判断本地Cache是否需要更新。也就是说可以延迟点间接的更新到当前数据库的最新状态。一开始也是想以这样的方式去实现参数生效功能,后来看了下pg_reload_conf()函数恍然大悟,何必这么麻烦,直接用postgres进程间信号即可,因为postgres已经有通知所有session重新读参数功能了,要做的就只要把参数写进去通知大家重读参数文件就可以了。
那么现在的问题就转化成了如何写参数了,遗憾的是没有发现内核有对postgresql.conf文件参数的写相关功能,postgresql.conf 文件是从 postgresql.conf.sample COPY过来的,并不是动态生成的。不过postgresql.conf有include_if_exists 用法,如果存在某个参数文件就追加到后面,那么我们就可以增加一个新的参数文件,里面就写我们在设置的参数值。
以函数方式实现,在date.c的增加相关代码:

extern char    *ConfigFileName;
extern bool     oracle_style;
extern FILE * AllocateFile(const char *name, const char *mode);
Datum swap_oracle_mode(PG_FUNCTION_ARGS)
{
    char conf_path[512] = { 0 };
    int pos = 0;
    int count = 1;
    char *tmpFile = ConfigFileName;
    FILE *fp;

    if (NULL == ConfigFileName)
    {
        ereport(ERROR,
            (errcode(ERRCODE_CONFIG_FILE_ERROR),
            errmsg("can't open the config file")));
    }

    while ('\0' != *tmpFile)        //找到参数文件路径
    {
        if (*tmpFile == '\\' || *tmpFile == '/')
        {
            pos = count;
        }
        count++;
        tmpFile++;
    }

    if (pos + strlen("oracle.conf") > sizeof(conf_path))    
    {
        elog(ERROR, "can't create the oracle.conf file");
    }

    memcpy(conf_path, ConfigFileName, pos);
    memcpy(conf_path + pos, "oracle.conf", strlen("oracle.conf"));  //生成新路径名字

    fp = AllocateFile(conf_path, "w+");                 
    if (NULL == fp)
    {
        ereport(ERROR,
            (errcode(ERRCODE_CONFIG_FILE_ERROR),
            errmsg("can't open the config file")));
        return;
    }
    else
    {
        if (oracle_style)                       //在新参数文件中写入参数命令
        {
            fprintf(fp, "oracle_style = off\n");
        }
        else
        {
            fprintf(fp, "oracle_style = on\n");
        }

        if (FreeFile(fp))
        {
            elog(ERROR,"can't write oracle.conf file ");
            return;
        }

        if (kill(PostmasterPid, SIGHUP))    /*****通知其它进程重读参数****/
        {
            ereport(WARNING,
                (errmsg("failed to send signal to postmaster: %m")));
        }
    }

    PG_RETURN_BOOL(true);
}

在pg_proc.h中增加函数注册

DATA(insert OID = 9995 (swap_oracle_mode   PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 16 "" _null_ _null_ _null_ _null_ _null_ swap_oracle_mode _null_ _null_ _null_));

执行swap_oracle_mode()函数刚修改oracle_style 参数值,覆写到新参数文件 oracle.conf,通知其它连接重读参数,当然别忘了在postgresql.conf中加上一句:

include_if_exists = 'oracle.conf'

小功告成,看看效果,session 1执行参数修改函数,session 2在session 1修改函数前后分别查oracle_style参数值。

postgres=#  ---session 1;
postgres=# show oracle_style;
 oracle_style
--------------
 on
(1 row)


postgres=# select swap_oracle_mode();
 swap_oracle_mode
------------------
 t
(1 row)


postgres=#  show oracle_style;
 oracle_style
--------------
 off
(1 row)

postgres=# ---session 2;
postgres=# show oracle_style;
 oracle_style
--------------
 on
(1 row)


postgres=# show oracle_style;       --session 1 swap_oracle_mode()执行前
 oracle_style                                
--------------
 on
(1 row)


postgres=#  show oracle_style;  --session 2 swap_oracle_mode()执行后
 oracle_style
--------------
 off
(1 row)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值