一直用的是Oracle,今天要在postgresql写个程序,查了半天的pg官方文档件才搞定。
官方的例子有点简单,我把项目中的程序直接发过来供后来者学习和参考。
备注: 1,这个程序功能是使2台服务器的postgresql数据库中的一个表保持一致。 2,加了进程重启功能。 3,postgresql有自动提交回滚功能,害的我在官方api文档找了半天的事务回滚在哪里(高手莫笑,哈哈) 4,程序最好总是在BEGIN和END之间操作数据库,哪怕仅仅是select操作。 5,若遇乱码问题,请在sql语句前加set client_encoding = 'GBK'; /* *Program Name : updateplicheck.c *Author : Liu Lin *Date : 20090701 */ #include "public.h" #include "db_manager.h" #include "libpq-fe.h" #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <fcntl.h>
static void sig_child(int signo); static void task_fork(); static void run_task();
int main(void) { int pid; //创建守护进程开始 if ((pid = fork()) < 0) { LOGLINE; LOG("创建进程操作失败"); exit(1); } if (pid > 0) exit(0); setsid(); signal(SIGHUP,SIG_IGN); umask(0); //创建守护进程结束 signal(SIGCHLD,sig_child); task_fork(); while (1) { pause(); } }
static void task_fork() { pid_t pid; if ((pid = fork()) < 0) { LOGLINE,LOG("创建子进程失败"); exit(1); } if (pid == 0) { signal(SIGCHLD,SIG_DFL); run_task(); exit(0); } }
static void run_task(void) { char conninfo[256] = {0}; PGconn *conn; //连接代理服务器数据库 PGresult *res; PGconn *conn2; //连接本地服务器数据库 PGresult *res2; int status; char sql_que[1024] = {0}; int i; int update_times = 0; while (update_times < 12*7)//每个进程只负责一周的更新,防止内存泄露 { update_times++; memset(conninfo,sizeof(conninfo)); strcpy(conninfo,"host=192.168.1.110 dbname=ydds user=postgres password=postgres port=5432 connect_timeout=30"); conn = PQconnectdb(conninfo); if(PQstatus(conn) != CONNECTION_OK) { LOGLINE; LOG("与更新源postgresql数据库连接失败,时间是[%s]",TIME()); PQfinish(conn); sleep(60*60); continue; } else { LOGLINE; LOG("与更新源postgresql数据库连接成功,时间是[%s]",TIME()); } memset(conninfo,"host=localhost dbname=ydds user=postgres password=postgres port=5432 connect_timeout=30"); conn2 = PQconnectdb(conninfo); if(PQstatus(conn2) != CONNECTION_OK) { LOGLINE; LOG("与本地postgresql数据库连接失败,时间是[%s]",TIME()); PQfinish(conn); PQfinish(conn2); sleep(60*60); continue; } else { LOGLINE; LOG("与本地postgresql数据库连接成功,时间是[%s]",TIME()); } res2 = PQexec(conn2,"BEGIN"); if(PQresultStatus(res2) != PGRES_COMMAND_OK) //成功完成一个不返回数据的命令 { LOGLINE; LOG("执行BEGIN失败[%s]",PQerrorMessage(conn)); PQclear(res2); PQfinish(conn); PQfinish(conn2); sleep(60*60); continue; } PQclear(res2); memset(sql_que,sizeof(sql_que)); sprintf(sql_que,"select adm_no,adm_name,pli_no,pli_name from bank_pli_check"); res = PQexec(conn,sql_que); status = PQresultStatus(res); if (status != PGRES_TUPLES_OK) //成功执行一个返回数据的查询查询 { LOGLINE; LOG("查询表bank_pli_check失败"); PQclear(res); PQfinish(conn); PQfinish(conn2); sleep(60*60); continue; } for (i = 0; i < PQntuples(res); i++) { memset(sql_que,"select pli_no from bank_pli_check where pli_no = '%s'",PQgetvalue(res,i,2)); res2 = PQexec(conn2,sql_que);//查看该条记录是否已经存在 status = PQresultStatus(res2); if (status != PGRES_TUPLES_OK)//注意一个碰巧检索了零条元组的SELECT仍然显示PGRES_TUPLES_OK { LOGLINE; LOG("查询表bank_pli_check失败"); PQclear(res); PQclear(res2); PQfinish(conn); PQfinish(conn2); sleep(60*60); continue; } if (PQntuples(res2) != 0) { LOGLINE; LOG("记录pli=[%s]已经在bank_pli_check存在",2)); PQclear(res2); } else { PQclear(res2); memset(sql_que,"insert into bank_pli_check (adm_no,pli_name) values ('%s','%s','%s')",0),1),2),3)); res2 = PQexec(conn2,sql_que);//没有的记录将更新到表里面 status = PQresultStatus(res2); if (status == PGRES_COMMAND_OK) { LOGLINE; LOG("记录pli=[%s]已经更新到bank_pli_check表里",2)); } else { LOGLINE; LOG("记录pli=[%s]插入bank_pli_check表失败",2)); } } } res2 = PQexec(conn2,"END"); PQclear(res); PQclear(res2); PQfinish(conn); PQfinish(conn2); sleep(60*60); } return; }
static void sig_child(int signo) { pid_t pid; int status; while ((pid = waitpid(-1,&status,WNOHANG)) > 0) { LOGLINE; LOG("子进程[%d]]退出, 时间是[%s]",pid,TIME()); task_fork(); } return; }
static int LOG_INIT(void){ time_t timep; struct tm *time_ptr = NULL; time(&timep); time_ptr = localtime(&timep); memset(g_log_file,sizeof(g_log_file)); sprintf(g_log_file,"%s%s.log.%d%02d%02d",LOG_PATH,__FILE__,(1900 + time_ptr->tm_year),(1 + time_ptr->tm_mon),(time_ptr->tm_mday)); memset(g_source_file,sizeof(g_source_file)); strcpy(g_source_file,__FILE__); return 0;} (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|