postgresql jdbc prepared 的通信过程的分析
2016-06-14 00:00
531 查看
摘要: 本文通过在数据包层来分析prepared的通信过程,加深对prepared的了解。
通过postgresql的官方文档,可以了解到与prepared整个过程相关的包大概包含parse, bind, describe , execute ,sync,这5个包是从客户端向服务端发送的。当服务端处理完毕这些包后会返回对应的parseComplete, bindComplete,rowDescription, rowdata, nodata 等等数据包作为回应。
本文想讲解的重点是bind包中关于结果字段格式的问题。从官方文档可以知道字段格式有两种:文本(0)和二进制(1)。那么哪些字段是文本格式,哪些字段是二进制格式呢。prepared中什么时候使用文本格式,什么时候使用二进制格式呢?
一,使用二进制格式的数据类型
从postgresql jdbc 9.4源码的AbstractJdbc2Connection.java文件的163行左右(代码段如下)来看。
只有协议版本在3及以上才会出现二进制的类型。并且在postgresql 小于8.0, 小于8.3 以及大于等于8.3的版本之间有一定的差异。
有时候为了不让某些类型通过二进制通信,则可以通过PGProperty来DISABLE这些类型即可。相反则ENABLE这些类型。
需要注意的是所有 版本中都不支持Oid.DATE进行二进制通信。(不管用户ENABLE与否)
排除以上 出现的类型外,其他的类型都使用文本进行通信。
二,prepared中使用二进制的时机
只有当针对同一个语句进行多次bind时,才会进行二进制的格式进行通信。第一次通信都是以文本的形式得到结果数据的。只有第二次及以后的调用对应的类型的字段的值才以二进制的格式进行通信。可以通过postgresql jdbc打开debug来观察。
从理论上面来讲,第一次发送parse和bind包时,根本就不知道表中字段的类型。故bind无法要求服务端以特定的格式返回数据。第二次发送bind时,由于已经存在第一次调用返回的字段信息,故可以知道要求返回特定格式的数据。
通过postgresql的官方文档,可以了解到与prepared整个过程相关的包大概包含parse, bind, describe , execute ,sync,这5个包是从客户端向服务端发送的。当服务端处理完毕这些包后会返回对应的parseComplete, bindComplete,rowDescription, rowdata, nodata 等等数据包作为回应。
本文想讲解的重点是bind包中关于结果字段格式的问题。从官方文档可以知道字段格式有两种:文本(0)和二进制(1)。那么哪些字段是文本格式,哪些字段是二进制格式呢。prepared中什么时候使用文本格式,什么时候使用二进制格式呢?
一,使用二进制格式的数据类型
从postgresql jdbc 9.4源码的AbstractJdbc2Connection.java文件的163行左右(代码段如下)来看。
[code=language-java]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时,由于已经存在第一次调用返回的字段信息,故可以知道要求返回特定格式的数据。
相关文章推荐
- postgresql jdbc 禁止二进制格式进行通信
- sql 的基础语句
- Mysql海量数据存储和解决方案第二篇 Mysql分表查询海量数据
- Mysql海量数据存储和解决方案第一篇 分布式DB方案
- 数据库中表的连接
- 那些可能被你忽略的MySQL优化技巧
- InnoDB源码分析--缓冲池(三)
- mysql 返回多列的方式
- Oracle 日期和时间的存储于处理
- 数据库连接池
- SQL注入漏洞产生的原因 ? 如何防止?
- PL/SQL 连接Oracle数据库
- oracle: sql 基础知识
- Mysql学习笔记
- mysql配置文件编写
- 有for SQLServer的OGG 12C版本么?
- ORACLE如何创建表空间和用户
- mysql创建索引
- mysql索引分类
- oracle的启动和关闭