文档章节

postgresql jdbc prepared 的通信过程的分析

harris2016
 harris2016
发布于 2016/06/14 17:18
字数 708
阅读 98
收藏 0

    通过postgresql的官方文档,可以了解到与prepared整个过程相关的包大概包含parse, bind, describe , execute ,sync,这5个包是从客户端向服务端发送的。当服务端处理完毕这些包后会返回对应的parseComplete, bindComplete,rowDescription, rowdata, nodata 等等数据包作为回应。

    本文想讲解的重点是bind包中关于结果字段格式的问题。从官方文档可以知道字段格式有两种:文本(0)和二进制(1)。那么哪些字段是文本格式,哪些字段是二进制格式呢。prepared中什么时候使用文本格式,什么时候使用二进制格式呢?

一,使用二进制格式的数据类型

    从postgresql jdbc 9.4源码的AbstractJdbc2Connection.java文件的163行左右(代码段如下)来看。

if (binaryTransfer && protoConnection.getProtocolVersion() >= 3) {
            binaryOids.add(Oid.BYTEA);
            binaryOids.add(Oid.INT2);
            binaryOids.add(Oid.INT4);
            binaryOids.add(Oid.INT8);
            binaryOids.add(Oid.FLOAT4);
            binaryOids.add(Oid.FLOAT8);
            binaryOids.add(Oid.TIME);
            binaryOids.add(Oid.DATE);
            binaryOids.add(Oid.TIMETZ);
            binaryOids.add(Oid.TIMESTAMP);
            binaryOids.add(Oid.TIMESTAMPTZ);
            binaryOids.add(Oid.INT2_ARRAY);
            binaryOids.add(Oid.INT4_ARRAY);
            binaryOids.add(Oid.INT8_ARRAY);
            binaryOids.add(Oid.FLOAT4_ARRAY);
            binaryOids.add(Oid.FLOAT8_ARRAY);
            binaryOids.add(Oid.FLOAT8_ARRAY);
            binaryOids.add(Oid.VARCHAR_ARRAY);
            binaryOids.add(Oid.TEXT_ARRAY);
            binaryOids.add(Oid.POINT);
            binaryOids.add(Oid.BOX);
            binaryOids.add(Oid.UUID);
        }        
        // the pre 8.0 servers do not disclose their internal encoding for
        // time fields so do not try to use them.
        if (!haveMinimumCompatibleVersion(ServerVersion.v8_0)) {
            binaryOids.remove(Oid.TIME);
            binaryOids.remove(Oid.TIMETZ);
            binaryOids.remove(Oid.TIMESTAMP);
            binaryOids.remove(Oid.TIMESTAMPTZ);
        }
        // driver supports only null-compatible arrays
        if (!haveMinimumCompatibleVersion(ServerVersion.v8_3)) {
            binaryOids.remove(Oid.INT2_ARRAY);
            binaryOids.remove(Oid.INT4_ARRAY);
            binaryOids.remove(Oid.INT8_ARRAY);
            binaryOids.remove(Oid.FLOAT4_ARRAY);
            binaryOids.remove(Oid.FLOAT8_ARRAY);
            binaryOids.remove(Oid.FLOAT8_ARRAY);
            binaryOids.remove(Oid.VARCHAR_ARRAY);
            binaryOids.remove(Oid.TEXT_ARRAY);
        }

        binaryOids.addAll(getOidSet(PGProperty.BINARY_TRANSFER_ENABLE.get(info)));
        binaryOids.removeAll(getOidSet(PGProperty.BINARY_TRANSFER_DISABLE.get(info)));

只有协议版本在3及以上才会出现二进制的类型。并且在postgresql 小于8.0, 小于8.3 以及大于等于8.3的版本之间有一定的差异。

 有时候为了不让某些类型通过二进制通信,则可以通过PGProperty来DISABLE这些类型即可。相反则ENABLE这些类型。

需要注意的是所有 版本中都不支持Oid.DATE进行二进制通信。(不管用户ENABLE与否)

排除以上 出现的类型外,其他的类型都使用文本进行通信。

二,prepared中使用二进制的时机

   只有当针对同一个语句进行多次bind时,才会进行二进制的格式进行通信。第一次通信都是以文本的形式得到结果数据的。只有第二次及以后的调用对应的类型的字段的值才以二进制的格式进行通信。可以通过postgresql jdbc打开debug来观察。

    从理论上面来讲,第一次发送parse和bind包时,根本就不知道表中字段的类型。故bind无法要求服务端以特定的格式返回数据。第二次发送bind时,由于已经存在第一次调用返回的字段信息,故可以知道要求返回特定格式的数据。

© 著作权归作者所有

共有 人打赏支持
harris2016
粉丝 10
博文 52
码字总数 30058
作品 0
杭州
程序员
ETL for Oracle to PostgreSQL 1 - Oracle Data Integrator (ODI)

标签 PostgreSQL , Oracle , ETL , Oracle Data Integrator , ODI 背景 原文 https://www.cdata.com/kb/tech/postgresql-jdbc-odi.rst 正文 ETL PostgreSQL in Oracle Data Integrator This ......

德哥
05/06
0
0
JAVA存取PostgreSQL二进制类型bytea

经过测试:JAVA存取PostgreSQL的bytea类型均存在内存的限制问题(存取的数据过大会出现out of memory内存溢出的问题),EnterpriseDB对此做了优化。 取PostgreSQL中的bytea,并存储到硬盘上....

YuanyuanL
2013/08/09
0
0
PostgreSQL jdbc multi-host 配置与简单HA、Load Balance实现

标签 PostgreSQL , HA , jdbc , multi host , targetsessionattrs 背景 pg jdbc 与libpq一样,都是PG的连接驱动,都支持multi-master ,同时pg jdbc还支持了loadbalance。 《PostgreSQL libp......

德哥
09/15
0
0
多平台向Postgresql 迁移

最近有个工作要把 一个SqlServer 迁移到 Postgresql 平台上,上网搜了搜,EnterpriseDB在这块做了很多工作, EnterpriseDB 的 Postgres Plus Advanced Server管理工具中有一个 mogiration t...

从前
2013/01/30
0
0
PostgreSQL 登陆登出(login logout)事件触发方法

标签 PostgreSQL , 事件触发器 , event trigger , hook , login hook , libpq 背景 PostgreSQL 支持event trigger,但是event局限于DDL。当发生DDL时,可以触发一些动作调用用户自定义的eve...

德哥
09/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

70.shell的函数 数组 告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.16/20.17 shell中的函数: ~1. 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段...

王鑫linux
今天
0
0
分布式框架spring-session实现session一致性使用问题

前言:项目中使用到spring-session来缓存用户信息,保证服务之间session一致性,但是获取session信息为什么不能再服务层获取? 一、spring-session实现session一致性方式 用户每一次请求都会...

WALK_MAN
今天
5
0
C++ yield()与sleep_for()

C++11 标准库提供了yield()和sleep_for()两个方法。 (1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周...

yepanl
今天
4
0
Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情。并发课题对于Java来说是一个又重要又难的一大块,除非气定神闲、精力满满,否则我本身是不敢随便写...

心中的理想乡
今天
31
0
shell学习之获取用户的输入命令read

在运行脚本的时候,命令行参数是可以传入参数,还有就是在脚本运行过程中需要用户输入参数,比如你想要在脚本运行时问个问题,并等待运行脚本的人来回答。bash shell为此提 供了read命令。 ...

woshixin
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部