pgjdbc源码分析
今天我们讲一讲pgjdbc。pgjdbc是postgresql的JDBC接口。其网址是https://jdbc.postgresql.org/.是开源软件,我们可以轻松的查看其代码,理解jdbc的工作原理。
一. 源代码目录结构
pgjdbc的源码结构如下图:

那么我们来一一看看各个模块都是做什么的吧。
1 core
该目录是程序的核心模块目录。
这里实现了大部分pgjdbc的基类和接口,例如statement query log type command connection类等等;
并且在此基础上的Connection的V3协议(V2版本的协议在新版本里已删除);
2 data source
该模块实现的是jdbc的数据源模块。其中:
ds目录下提供基础的数据源支持;
xa目录下提供支持分布式事务的数据源;
3 common api
jdbc
jdbc2
jdbc3
Driver.java
这些目录下提供了共通的jdbc驱动接口。
4 extend api
这部分是postgresql独有的特殊命令和类型的支持。其中:
copy目录下的代码支持postgresql的COPY命令;
geometric目录下的代码 支持postgresql的集合类型;
fastpath目录下的代码是PostgreSQL提供一种快速路径接口来向服务器发送简单的函数调用。这个接口在某种程度上已被废弃,因为我们可以通过创建一个定义该函数调用的预备语句来达到类似或者更强大的功能;
largeobject目录下的代码提供对Postgresql的大对象数据类型的支持;
5 security api
ssl sspi gss这些很显然,这是对安全相关的认证的支持。
6 until
该目录下的代码提供一些工具库的实现。例如message类、 exception类
7 hostchooser
该目录下的代码提供了对连接字符串中targetServerType参数的支持。支持特定类型的host的选择(目前指定该参数为preferSlave有点bug)。
8 osgi
目录下的代码实现了OSGi(Open Service Gateway Initiative)技术是Java动态化模块化系统的一系列规范(老实说并不是太懂)。
二. 调用关系
调用关系的话,我们大家应该还是蛮熟悉的。不多说,举例子吧。
假设我们执行这样一个查询:
select * from hr.employees;
pgjdbc的工作时序大概下面这个样子(在网上找的图,侵删):

这里面唯一神秘的就是executeQuery()执行后,客服端和database的交互细节。下面我们简单的分析下这一段的协议流吧。
三. 协议流
PostgreSQL的客户端与服务端通过协议消息通信,下面以pgjdbc执行一个简单的SELECT为例说明
已定义以下的表。
create table ecpg_test(tint int, name text);
insert into ecpg_test values (12,'qwe');
执行的SELECT语句
select * from ecpg_test where tint =12
SELECT执行的流程
我们用一个java程序去连接postgresql。为了追踪log,我们如下设置:
1.客户端:连接字符串里面加上参数loggerLevel=TRACE来追踪这次连接以及查询
2.服务端:设置参数client_min_messages和log_min_messages为debug5(这里我为了log完整起见,其实没必要设置这么高)
运行完程序,log如下(为方便观察,我就摘抄了一部分,其它的我省略了):
.
.
.
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@19d449fc, maxRows=0, fetchSize=0, flags=17
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl sendParse
FINEST: FE=> Parse(stmt=null,query="select * from ecpg_test where tint =12",oids={})
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=null,portal=null)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
FINEST: FE=> Describe(portal=null)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl sendSync
FINEST: FE=> Sync
.
.
.
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl processResults
FINEST: <=BE ParseComplete [null]
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl processResults
FINEST: <=BE BindComplete [unnamed]
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl receiveFields
FINEST: <=BE RowDescription(2)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl receiveFields
FINEST: Field(tint,INT4,4,T)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl receiveFields
FINEST: Field(name,TEXT,65535,T)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl processResults
FINEST: <=BE DataRow(len=5)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
FINEST: <=BE CommandStatus(SELECT 1)
11 14, 2017 3:26:27 午後 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
FINEST: <=BE ReadyForQuery(I)
.
.
.
11 14, 2017 3:02:20 午後 org.postgresql.core.QueryExecutorBase close
FINEST: FE=> Terminate
Process finished with exit code 0
可以看到,客户端在执行execute时,依次进行了sendParse、sendBind、sendDescribePortal、sendExecute、sendSync这些操作。
然后服务端对应这些操作分别对应给了处理和相应:ParseComplete、BindComplete、RowDescription、DataRow等等。
这些操作写在org.postgresql.core.v3包下的QueryExecutorImpl.java中。更详细一点的说,是在函数中:
private void sendOneQuery(SimpleQuery query, SimpleParameterList params, int maxRows,
int fetchSize, int flags)
其实这里有一个疑问,在sendOneQuery()函数里,上面所说的客户端和服务端操作是按照次序一一对应的执行的。手画一个草图比如:
client ------------------ --- server
|sendParse() |
| --------------------------> |
| <------------------------- |
| ParseComplete |
|sendBind() |
| -------------------------> |
| <------------------------- |
| BindComplete |
.
.
.
也就是说,是有严格的次序关系的。可是我们看log可以发现,客户端的这些操作是一次性发到服务端,服务端也是处理完一次性发回的。那么为什么会不一致呢?
请教了朋友和同事,原来是:
为了优化网络传输。将多次发送的数据集中到一次发送,提高效率。
好的,今天就到这里。
引用:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4150218
pgjdbc源码分析的更多相关文章
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- ABP源码分析二:ABP中配置的注册和初始化
一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...
- ABP源码分析三:ABP Module
Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...
随机推荐
- 一张图理清ASP.NET Core启动流程
1. 引言 对于ASP.NET Core应用程序来说,我们要记住非常重要的一点是:其本质上是一个独立的控制台应用,它并不是必需在IIS内部托管且并不需要IIS来启动运行(而这正是ASP.NET Cor ...
- window开启remote desktop服务
确定自己的PC支持远程桌面 1 先确定被遥控的电脑的系统必须是Professional或Enterprise以上版本,家庭版不支持远程桌面.以Win8.1(7和8同理)为例,依次打开控制面板→系统 ...
- Python 基础之函数、深浅copy,set及练习
三元运算符通常在Python里被称为条件表达式,这些表达式基于真(true)/假(not)的条件判断,在Python 2.4以上才有了三元操作. 语法格式: X if C else Y 有了三元表达式 ...
- dmesg和addr2line 定位 segfault
程序长时间运行崩溃,但是没有保存core dump消息.可以用下面的方法定位出程序出错位置: 1. 用dmesg查找出错的代码段地址 ip 000000000041ccec 发生错误时指令的地址, s ...
- MyBatis开发中解决返回字段不全的问题
场景重现: mybatis 在查询的时候,可以返回Map,但是一旦这个字段为空(null)的时候,map里就没有了.我用的是mysql数据库,除了在查询语句上做ifnull判断给它默认值外,有没的别的 ...
- 使用olami sdk实现一个语音查询股票的iOS程序
前言 在目前的软件应用中,输入方式还是以文字输入方式为主,但是语音输入的方式目前应用的越来越广泛.在这里介绍一个使用 Olami SDK 编写的一个使用语音输入查询股票的APP Olami SDK的介 ...
- ST40 自制 JTAG 适配器
// 文章首发于 https://zhuanlan.zhihu.com/p/28762429 // 但是不知道为什么搜索引擎还没有收录,便在博客再次发布. 0. 引言 意法半导体生产的 SH4 架构的 ...
- windows中vim-airline研究笔记
vim-airline网上的介绍与安装教程一大堆,我就不累述了 但是,在win下如何让airline插件正常显示箭头等特殊字符着实让我头疼了不少. 最初,我是用的monaco字体 但正如你所见,并没有 ...
- JFinal快速上手及注意事项
官方手册虽然写的很详细但是忽略的很多小的细节方面,不看源码,网络资料又少,很多新手找不到解决办法.所以养成出了问题,多看源码的习惯 部署helloJFinal 项目结构 - 相关代码 `package ...
- word2vec 在 非 自然语言处理 (NLP) 领域的应用
word2vec 本来就是用来解决自然语言处理问题的,它在 NLP 中的应用是显然的. 比如,你可以直接用它来寻找相关词.发现新词.命名实体识别.信息索引.情感分析等:你也可以将词向量作为其他模型的输 ...