postgresql获取表最后更新时间(通过发布订阅机制将消息发送给应用程序)

一、创建测试表

CREATE TABLE weather(
city varchar(80),
temp_lo int,  --最低温度
temp_hi int,  --最高温度
prcp real,     --湿度
date date
);

二、创建触发器函数

create or replace function table_update_notify() returns trigger as $$
begin 
    perform pg_notify('table_update',json_build_object('table',TG_TABLE_NAME,'timestamp',current_timestamp)::text);
    return new;
end;
$$ language plpgsql;

三、创建触发器

drop trigger if exists n_weather_u on weather;
create trigger n_weather_u after insert or update or delete on weather
for each statement execute procedure table_update_notify();

四、应用程序代码

代码有重连机制,数据库服务器停止或者网络断开应用程序不退出,数据库服务起来或者网络恢复后应用程序会自动重连并重新订阅消息

#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>

static void exit_nicely(PGconn *conn)
{       
        PQfinish(conn);
        exit(1);
}

int main(int argc,char **argv)
{
        const char *conninfo;
        PGconn *conn;
        PGresult *res;
        PGnotify *notify;

        conninfo = "hostaddr=192.168.147.1 port=5432  dbname=postgres user=postgres password=123456";
        conn = PQconnectdb(conninfo);
        if(PQstatus(conn) != CONNECTION_OK)
        {       
                fprintf(stderr,"connection to database failed:%s",PQerrorMessage(conn));
                exit_nicely(conn);
        }

        res = PQexec(conn,"listen table_update");
        if(PQresultStatus(res) != PGRES_COMMAND_OK)
        {
                fprintf(stderr,"listen command failed:%s",PQerrorMessage(conn));
                PQclear(res);
                exit_nicely(conn);
        }
        
        PQclear(res);

        while(1)
        {
                //执行select 1命令来判断数据库连接是否正常,不正常则自动重连,并重新订阅通知
                PGresult *res_getallrows;
                res_getallrows = PQexec(conn,"select 1;");
            //    printf("PQresultStatus(res_getallrows)=%d\n",PQresultStatus(res_getallrows));
                if(PQresultStatus(res_getallrows) != PGRES_TUPLES_OK)
                {
                    conn = PQconnectdb(conninfo);
                    if(PQstatus(conn) != CONNECTION_OK)
                    {       
                        usleep(1000);
                        continue;
                    }
                    else
                    {
                        res = PQexec(conn,"listen table_update");
                        if(PQresultStatus(res) != PGRES_COMMAND_OK)
                        {
                            PQclear(res);
                            usleep(1000);
                            continue;
                        }
                    }
                }
            
                PQconsumeInput(conn);
                while((notify = PQnotifies(conn)) != NULL)
                {
                        fprintf(stderr,"async notify of '%s' received from backend PID %d,extra:%s\n",notify->relname,notify->be_pid,notify->extra);
                        PQfreemem(notify);
                }
                
                usleep(1000);
        }

        fprintf(stderr,"Done.\n");
        PQfinish(conn);
        return 0;
}

编译:gcc -I/opt/pgsql/include -L/opt/pgsql/lib -o test testpq.c -lpq

五、测试

服务器端执行sql

insert into weather values('nanjing',20,40,0.25,'2018-06-29');
update weather set temp_lo = 18 where city = 'nanjing';
delete from weather where city = 'nanjing'

应用程序获取表变化时间

posted @ 2018-07-10 08:41  Luis Yang  阅读(1797)  评论(0编辑  收藏  举报