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 =12SELECT執行的流程
我們用一個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=> TerminateProcess 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 | . . .也就是說,是有嚴格的次序關系的??墒俏覀兛磍og可以發現,客戶端的這些操作是一次性發到服務端,服務端也是處理完一次性發回的。那么為什么會不一致呢?
請教了朋友和同事,原來是:
為了優化網絡傳輸。將多次發送的數據集中到一次發送,提高效率。
好的,今天就到這里。
引用:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4150218
轉載于:https://www.cnblogs.com/flying-tiger/p/7812804.html
總結
以上是生活随笔為你收集整理的pgjdbc源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS 从实际出发理解多线程
- 下一篇: [NOIP2017]逛公园 最短路+拓