pgjdbc源码分析
今天我們講一講pgjdbc。pgjdbc是postgresql的JDBC接口。其網(wǎng)址是https://jdbc.postgresql.org/.是開源軟件,我們可以輕松的查看其代碼,理解jdbc的工作原理。
一. 源代碼目錄結(jié)構(gòu)
pgjdbc的源碼結(jié)構(gòu)如下圖:
那么我們來一一看看各個(gè)模塊都是做什么的吧。
1 core
該目錄是程序的核心模塊目錄。
這里實(shí)現(xiàn)了大部分pgjdbc的基類和接口,例如statement query log type command connection類等等;
并且在此基礎(chǔ)上的Connection的V3協(xié)議(V2版本的協(xié)議在新版本里已刪除);
2 data source
該模塊實(shí)現(xiàn)的是jdbc的數(shù)據(jù)源模塊。其中:
ds目錄下提供基礎(chǔ)的數(shù)據(jù)源支持;
xa目錄下提供支持分布式事務(wù)的數(shù)據(jù)源;
3 common api
jdbc
jdbc2
jdbc3
Driver.java
這些目錄下提供了共通的jdbc驅(qū)動(dòng)接口。
4 extend api
這部分是postgresql獨(dú)有的特殊命令和類型的支持。其中:
copy目錄下的代碼支持postgresql的COPY命令;
geometric目錄下的代碼 支持postgresql的集合類型;
fastpath目錄下的代碼是PostgreSQL提供一種快速路徑接口來向服務(wù)器發(fā)送簡單的函數(shù)調(diào)用。這個(gè)接口在某種程度上已被廢棄,因?yàn)槲覀兛梢酝ㄟ^創(chuàng)建一個(gè)定義該函數(shù)調(diào)用的預(yù)備語句來達(dá)到類似或者更強(qiáng)大的功能;
largeobject目錄下的代碼提供對(duì)Postgresql的大對(duì)象數(shù)據(jù)類型的支持;
5 security api
ssl sspi gss這些很顯然,這是對(duì)安全相關(guān)的認(rèn)證的支持。
6 until
該目錄下的代碼提供一些工具庫的實(shí)現(xiàn)。例如message類、 exception類
7 hostchooser
該目錄下的代碼提供了對(duì)連接字符串中targetServerType參數(shù)的支持。支持特定類型的host的選擇(目前指定該參數(shù)為preferSlave有點(diǎn)bug)。
8 osgi
目錄下的代碼實(shí)現(xiàn)了OSGi(Open Service Gateway Initiative)技術(shù)是Java動(dòng)態(tài)化模塊化系統(tǒng)的一系列規(guī)范(老實(shí)說并不是太懂)。
二. 調(diào)用關(guān)系
調(diào)用關(guān)系的話,我們大家應(yīng)該還是蠻熟悉的。不多說,舉例子吧。
假設(shè)我們執(zhí)行這樣一個(gè)查詢:
select * from hr.employees;pgjdbc的工作時(shí)序大概下面這個(gè)樣子(在網(wǎng)上找的圖,侵刪):
這里面唯一神秘的就是executeQuery()執(zhí)行后,客服端和database的交互細(xì)節(jié)。下面我們簡單的分析下這一段的協(xié)議流吧。
三. 協(xié)議流
PostgreSQL的客戶端與服務(wù)端通過協(xié)議消息通信,下面以pgjdbc執(zhí)行一個(gè)簡單的SELECT為例說明
已定義以下的表。
create table ecpg_test(tint int, name text); insert into ecpg_test values (12,'qwe');執(zhí)行的SELECT語句
select * from ecpg_test where tint =12SELECT執(zhí)行的流程
我們用一個(gè)java程序去連接postgresql。為了追蹤log,我們?nèi)缦略O(shè)置:
1.客戶端:連接字符串里面加上參數(shù)loggerLevel=TRACE來追蹤這次連接以及查詢
2.服務(wù)端:設(shè)置參數(shù)client_min_messages和log_min_messages為debug5(這里我為了log完整起見,其實(shí)沒必要設(shè)置這么高)
運(yùn)行完程序,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=> TerminateProcess finished with exit code 0可以看到,客戶端在執(zhí)行execute時(shí),依次進(jìn)行了sendParse、sendBind、sendDescribePortal、sendExecute、sendSync這些操作。
然后服務(wù)端對(duì)應(yīng)這些操作分別對(duì)應(yīng)給了處理和相應(yīng):ParseComplete、BindComplete、RowDescription、DataRow等等。
這些操作寫在org.postgresql.core.v3包下的QueryExecutorImpl.java中。更詳細(xì)一點(diǎn)的說,是在函數(shù)中:
private void sendOneQuery(SimpleQuery query, SimpleParameterList params, int maxRows,int fetchSize, int flags)其實(shí)這里有一個(gè)疑問,在sendOneQuery()函數(shù)里,上面所說的客戶端和服務(wù)端操作是按照次序一一對(duì)應(yīng)的執(zhí)行的。手畫一個(gè)草圖比如:
client ------------------ --- server|sendParse() || --------------------------> || <------------------------- || ParseComplete ||sendBind() || -------------------------> || <------------------------- || BindComplete | . . .也就是說,是有嚴(yán)格的次序關(guān)系的。可是我們看log可以發(fā)現(xiàn),客戶端的這些操作是一次性發(fā)到服務(wù)端,服務(wù)端也是處理完一次性發(fā)回的。那么為什么會(huì)不一致呢?
請(qǐng)教了朋友和同事,原來是:
為了優(yōu)化網(wǎng)絡(luò)傳輸。將多次發(fā)送的數(shù)據(jù)集中到一次發(fā)送,提高效率。
好的,今天就到這里。
引用:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4150218
轉(zhuǎn)載于:https://www.cnblogs.com/flying-tiger/p/7812804.html
總結(jié)
以上是生活随笔為你收集整理的pgjdbc源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS 从实际出发理解多线程
- 下一篇: [NOIP2017]逛公园 最短路+拓