今天我们讲一讲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源码分析的更多相关文章

  1. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  2. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  3. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  4. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  5. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  6. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  7. java使用websocket,并且获取HttpSession,源码分析

    转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...

  8. ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...

  9. ABP源码分析三:ABP Module

    Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...

随机推荐

  1. SQL Server XML数据解析

    --5.读取XML --下面为多种方法从XML中读取EMAIL DECLARE @x XML SELECT @x = ' <People> <dongsheng> <In ...

  2. Jquery实现弹出选择框选择后返回,支持多级分类

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  3. commons-pool与commons-pool2连接池

    commons-pool和commons-pool2是用来建立对象池的框架,提供了一些将对象池化必须要实现的接口和一些默认动作.对象池化之后可以通过pool的概念去管理其生命周期,例如对象的创建,使用 ...

  4. RabbitMQ高可用集群配置

    1.安装RabbitMQ 1)下载和安装erlang 下载erlang wget http://www.rabbitmq.com/releases/erlang/erlang-18.1-1.el6.x ...

  5. 有人提了一个问题:一定要RESTful吗?

    写在前面的话 这个问题看起来就显得有些萌,或者说类似的问题都有些不靠谱,世上哪有那么多一定的事情,做开发都不一定做多久呢,所以说如果你有这个疑问的话是真真有点儿不着调,不过可能也就是随口一问吧,没有深 ...

  6. 国内为什么没有好的 Stack Overflow 的模仿者?,因为素质太低?没有分享精神?

    今天终于在下班前搞定一个技术问题,可以准时下班啦.当然又是通过StackOverflow找到的解决思路,所以下班路上和同事顺便聊起了它,两个资深老程序猿,还是有点感叹,中国的程序员群体人数应该不少,为 ...

  7. Appium-desktop安装与使用

    Appium-desktop是什么? 项目描述: Appium Server and Inspector in Desktop GUIs for Mac, Windows, and Linux. Ap ...

  8. 张高兴的 Windows 10 IoT 开发笔记:BH1750FVI 光照度传感器

    BH1750FVI 是一款 IIC 接口的数字型光强度传感器集成电路.下面介绍一下其在 Windows 10 IoT Core 环境下的用法. 项目运行在 Raspberry Pi 2/3 上,使用 ...

  9. CSS3动画 transition和animation的用法和区别

    transition和animation都是CSS3新增的特性,使用时需要加内核 浏览器 内核名称 W3C   IE  -ms-  Chrome/Safari -webkit-   Firefoc - ...

  10. Fastify 系列教程一(路由和日志)

    介绍 Fastify是一个高度专注于以最少开销和强大的插件架构,为开发人员提供最佳体验的Web框架. 它受到了 Hapi 和 Express 的启发,是目前最快的 Node 框架之一. Fastify ...