博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Postgres Hooks
阅读量:7107 次
发布时间:2019-06-28

本文共 4360 字,大约阅读时间需要 14 分钟。

hot3.png

使用PostgreSQL中hook,可以不重新编译中断或者改变PG行为。

1.经常使用的Hook汇总 Hook

Initial releasecheck_password_hook 9.0ClientAuthentication_hook 9.1ExecutorStart_hook 8.4ExecutorRun_hook 8.4ExecutorFinish 8.4ExecutorEnd_hook 8.4ExecutorCheckPerms_hook 9.1ProcessUtility_hook 9.0Hook Used in Initial releaseexplain_get_index_name_hook 8.3ExplainOneQuery_hookIndexAdvisor 8.3fmgr_hook sepgsql 9.1get_attavgwidth_hook 8.4get_index_stats_hook 8.4get_relation_info_hookplantuner 8.3get_relation_stats_hook 8.4join_search_hooksaio 8.3needs_fmgr_hook sepgsql 9.1object_access_hook sepgsql 9.1planner_hook planinstr 8.3shmem_startup_hook pg_stat_statements 8.4

2.Hook工作原理分析

PG中hook如何工作

Hooks存在一个全局函数指针;并初始为NULL;当PG想使用一个hook时,检查这个全局函数指针,假如被设置,则执行函数。

如何设置函数指针hook函数定义在共享库中;在加载的时候,PG调用共享库中的_PG_init()函数;_PG_init函数设置函数指针(一般会把原来的指针保存)。如何清除函数指针在卸载时,PG调用共享库中的_PG_fini()函数;_PG_fini函数需要重新设置函数指针(通常将原来的指针恢复)。

3 实例

3.1 ClientAuthentication_hook

定义
/* src/include/libpq/auth.h */ /* Hook for plugins to get control in ClientAuthentication() */typedef void (*ClientAuthentication_hook_type) (Port *, int);extern PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook;
设置
/* src/backend/libpq/auth.c *//** This hook allows plugins to get control following client authentication,  * but before the user has been informed about the results.  It could be used  * to record login events, insert a delay after failed authentication, etc.  */ ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
检查和执行
/* src/backend/libpq/auth.c *//** Client authentication starts here.  If there is an error, this   * function does not return and the backend process is terminated.   */  voidClientAuthentication(Port *port){  //...      	if (ClientAuthentication_hook) (*ClientAuthentication_hook) (port, status);  //...  }
说明

控制:客户端认证之后,通知用户之前 用处:记录登录事件;认证失败后插入一段延迟

用到此hook的模块

auth_delay;sepgsql;connection_limits

ClientAuthentication_hook函数介绍
两个参数 f(Port *port, int status)

Port结构位于 src/include/libpq/libpq-be.h部分字段如下

typedef struct Port{    pgsocket    sock; 		/* File descriptor */    bool        noblock; 		/* is the socket in non-blocking mode? */    ProtocolVersion proto; 		/* FE/BE protocol version */    SockAddr    laddr; 			/* local addr (postmaster) */    SockAddr    raddr; 			/* remote addr (client) */    char       *remote_host;    	/* name (or ip addr) of remote host */    char       *remote_hostname;	/* name (not ip addr) of remote host, if  available */    char       *remote_port;    	/* text rep of remote port */    char       *database_name;    char       *user_name;    char       *cmdline_options;    List       *guc_options;} Port;

Status为状态代码--STATUS_ERROR,STATUS_OK等

实例

写一个具体使用案例:假如某个文件存在则禁止连接。

需要两个函数:

安装hook检查文件可用性,决定允许或拒绝连接

添加contrib/my_client_auth目录

添加文件:Makefile my_client_auth.c

/* -----------------** my_client_auth.c            ** Copyright (C) 2010-2011, PostgreSQL Global Development Group ** IDENTIFICATION **      contrib/my_client_auth/my_client_auth.c ** ----------------- */#include 
#include
#include "postgres.h"#include "fmgr.h"#include "libpq/auth.h"PG_MODULE_MAGIC;void _PG_init(void);/* Original Hook */static ClientAuthentication_hook_type next_client_auth_hook = NULL;/** Check authentication */static voidmy_client_auth(Port *port, int status){ struct stat buf; if (next_client_auth_hook) (*next_client_auth_hook) (port, status); if (status != STATUS_OK) return; if(!stat("/tmp/connection.stopped", &buf)) ereport(FATAL, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Connection not authorized!!")));}/** Module Load Callback */void_PG_init(void){ /* Install Hooks */ next_client_auth_hook = ClientAuthentication_hook; ClientAuthentication_hook = my_client_auth;}
#contrib/my_client_auth/MakefileMODULES = my_client_authPGFILEDESC = "my_client_auth - Writing My ClientAuthentication_hook"ifdef USE_PGXSPG_CONFIG = pg_config	PGXS := $(shell $(PG_CONFIG) --pgxs)include $(PGXS)else	subdir = contrib/my_client_auth	top_builddir = ../..include $(top_builddir)/src/Makefile.global	include $(top_srcdir)/contrib/contrib-global.mkendif

使用 make && make install

data/postgres.conf配置文件汇总添加:

shared_preload_libraries = 'my_client_auth'

重启数据库

/tmp下创建connection.stopped文件

psql连接报错:

psql: FATAL: Connection not authorized!!

转载于:https://my.oschina.net/innovation/blog/742179

你可能感兴趣的文章
阿里云Ubuntu部署java web(2) - 配置tomcat
查看>>
TexturePacker 算法
查看>>
对象化的Http和请求对象HttpRequest
查看>>
Codeforces Round #312 (Div. 2) ABC题解
查看>>
INBOUND_CONNECT_TIMEOUT与SQLNET.INBOUND_CONNECT_TIMEOUT小结
查看>>
LeetCode:Palindrome Number
查看>>
iOS开发--storyboard适配pin
查看>>
Sql server存储过程中常见游标循环用法
查看>>
Codeforces Beta Round #6 (Div. 2 Only) A. Triangle 水题
查看>>
[VS 2015] VS2015 完整ISO镜像包
查看>>
工厂模式与老化模式驱动中分别添加内容
查看>>
linux bash快捷键
查看>>
System.Guid ToString五中格式
查看>>
编写高质量代码:改善Java程序的151个建议(第8章:多线程和并发___建议122~125)
查看>>
刘未鹏的博中带的技术博客链接
查看>>
Unity3D研究院之Machine动画脚本自动生成AnimatorController(七十一)
查看>>
css圆环百分比
查看>>
Selenium2+python自动化1-环境搭建
查看>>
机器学习十大算法之KNN(K最近邻,k-NearestNeighbor)算法
查看>>
C#自动识别文件编码
查看>>