44.2. 消息流

本節描述消息流。以及每種消息類型的語意。 (每種信息的準確表現細節在 Section 44.4 裡。) 因連接的狀態不同,存在幾種不同的子協議: 啟動(startup),查詢(query),函數調用(function call)和 COPY 和結束(termination)。 還有用于通知響應和命令取消的特殊信息,這些特殊信息可能在啟動階段過後的任何時間產生。

44.2.1. 啟動

要開始一個會話,前端打開一個與服務器的連接並且發送一個啟動消息。 這個消息包括用戶名以及用戶希望與之連接的數據庫; 它還標識要使用的特定的協議版本。(另外,啟動信息可以包括用于運行時參數的額外設置。) 服務器然後就使用這些信息以及它的配置文件的內容 (比如 pg_hba.conf)以判斷這個連接是否可以接受,以及需要什麼樣的額外的認證(如果需要)。

然後服務器就發送合適的認證請求信息,前端必須用合適的認證響應信息來響應(比如一個口令)。 理論上講,這樣的認證請求/響應循環可能需要多次迭代,但是目前的認證方法都不需要超過一次的請求和響應。 有些方法則根本不需要前端的響應,因此就沒有認證請求發生。

認證週期的結束要麼是以服務器的拒絕連接(ErrorResponse), 要麼是以 AuthenticationOK 結束的。

這個階段來自服務器可能消息是:

ErrorResponse

連接請求被拒絕。 然後服務器馬上關閉聯接。

AuthenticationOk

認證交換成功完成.

AuthenticationKerberosV4

現在前端必須與服務器進行一次 Kerberos V4 認證對話(在這裡沒有描述,Kerberos 規範的一部分)。 如果對話成功,服務器響應一個 AuthenticationOk (認證成功)信息, 否則它響應一個 ErrorResponse (錯誤響應)。

AuthenticationKerberosV5

現在前端必須與服務器進行一次 Kerberos V5 認證對話(在這裡沒有描述,Kerberos 規範的一部分)。 如果對話成功,服務器響應一個 AuthenticationOk (認證成功)信息, 否則它響應一個 ErrorResponse (錯誤響應)。

AuthenticationCleartextPassword

現在前端必須明文形式發送一個包含口令的 PasswordMessage (未加密口令)包。 如果這是正確的口令,服務器用一個 AuthenticationOk 包響應,否則它響應一個 ErrorResponse 包。

AuthenticationCryptPassword

現在前端必須發送一個 PasswordMessage 包,該包包含用 crypt(3) 加密的口令,加密時使用了在 AuthenticationCryptPassword 消息裡聲明的 2 字節鹽粒。如果這是正確口令,服務器用一個 AuthenticationOk 響應,否則它用一個 ErrorResponse 響應。

AuthenticationMD5Password

現在前端必須發送一個包含用 MD5 加密的口令的 PasswordMessage, 加密時使用了在 AuthenticationMD5Password 消息裡聲明的 4 字符鹽粒。 如果這是正確口令,服務器用一個 AuthenticationOk 響應,否則它用一個 ErrorResponse 響應。

AuthenticationSCMCredential

這個響應只對那些支持 SCM 信任消息的本地 Unix 域連接出現。 前端必須發出一條 SCM 信任消息然後發送一個數據字節。 (數據字節的內容並不會被注意; 它的作用只是確保服務器等待了足夠長的時間來接受信任信息。)如果信任是可以接受的, 那麼服務器用 AuthenticationOk 響應,否則用 ErrorResponse 響應。

如果前端不支持服務器要求的認證方式,那麼它應該馬上關閉聯接。

在收到 AuthenticationOk 包之後, 前端必須等待來自後端的更多消息。在這個階段會啟動一個後端進程, 而前端只是一個感興趣的看熱鬧的。啟動嘗試仍然有可能失敗(ErrorResponse), 但是通常情況下,後端將發送一些 ParameterStatus 消息,BackendKeyData, 以及最後 ReadyForQuery。

在這個階段,後端將嘗試應用任何在啟動消息裡給出額外的運行時參數設置。 如果成功,這些值將成為會話缺省。錯誤將導致 ErrorResponse 並退出。

這個階段來自後端的可能消息是:

BackendKeyData

這個消息提供了密鑰(secret-key)數據, 前端如果想要在稍後發出取消的請求, 則必須保存這個數據。前端不應該響應這個信息, 但是應該繼續偵聽等待 ReadyForQuery 消息。

ParameterStatus

這個消息告訴前端有關後端參數的當前(初始化)設置,比如 client_encoding 或者 DateStyle 等。前端可以忽略這些信息,或者記錄其設置用于將來使用; 參閱 Section 44.2.6 獲取更多細節。前端不應該響應這些信息, 而是應該繼續偵聽 ReadyForQuery 消息。

ReadyForQuery

後端啟動成功,前端現在可以發出命令.

ErrorResponse

後端啟動失敗.在發送完這個消息之後聯接被關閉.

NoticeResponse

發出了一個警告信息。前端應該顯示這個信息, 並且繼續等待 ReadyForQuery 或 ErrorResponse。

後端在每個查詢循環後都會發出一個相同的 ReadyForQuery 消息。 前端可以合理地認為 ReadyForQuery 是一個查詢循環的開始 (而 BackendKeyData 表明啟動階段的成功完成), 或者認為 ReadyForQuery 是啟動階段和每個隨後查詢循環的結束, 具體是那種情況取決于前端的編碼需要。

44.2.2. 簡單查詢

一個查詢循環是由前端發送一條 Query 消息給後端進行初始化的。 這條消息包含一個用文本字串表達的 SQL 命令(或者一些命令)。 後端根據查詢命令字串的內容發送一條或者更多條響應消息給前端, 並且最後是一條 ReadyForQuery 響應信息。 ReadyForQuery 通知前端它可以安全地發送新命令了。 (實際上前端不必在發送其它命令之前等待 ReadyForQuery,但是這樣一來, 前端必須負責區分早先發出的命令失敗,而稍後發出的命令成功的情況。)

從後端來的可能的消息是:

CommandComplete

一個 SQL 命令正常結束.

CopyInResponse

後端已經準備好從前端拷貝數據到一個表裡面去。 又見 Section 44.2.5

CopyOutResponse

後端已經準備好從一個表裡拷貝數據到前端裡面去。 又見 Section 44.2.5

RowDescription

表示為了響應一個 SELECTFETCH,等的查詢, 將要返回一個行。這條消息的內容描述了這行的字段布局。這條消息後面將跟著每個返回給前端的行一個的 DataRow 消息。

DataRow

SELECTFETCH,等查詢返回的結果集中的一行。

EmptyQueryResponse

識別了一個空的查詢字串.

ErrorResponse

出錯了。

ReadyForQuery

查詢字串的處理完成。 發送一個獨立的消息來標識這個是因為查詢字串可能包含多個 SQL 命令。 (CommandComplete 只是標記一條 SQL 命令處理完畢,而不是整個字串。) ReadyForQuery 總會被發送,不管是處理成功結束還是產生錯誤。

NoticeResponse

發送了一個與查詢有關的警告信息。 注意信息是附加在其他響應上的,也就是說, 後端將繼續處理該命令。

SELECT (或其它返回結果集的查詢,比如 EXPLAINSHOW) 查詢的響應信息通常包含 RowDescription,零個或者多個 DataRow 消息,以及最後的 CommandComplete。 從前端來回的 COPY 調用Section 44.2.5裡提到的特殊的協議。 所有其他查詢類型通常只生成一個 CommandComplete 消息。

因為查詢字串可能包含若幹個查詢(用分號分隔), 所以在後端完成查詢字串的處理之前可能有好幾個這樣的響應序列。 如果整個字串已經處理完,後端已經準備好接受新查詢字串的時候則發出 ReadyForQuery 消息。

如果收到一個完全空(除了空白之外沒有內容)的查詢字串, 那麼響應是一條 EmptyQueryResponse 後面跟著 ReadyForQuery。

在出現錯誤的時候,發出一個 ErrorResponse 消息,後面跟著 ReadyForQuery。 查詢字串的所有後繼的處理都被 ErrorResponse 中止(即使裡面還有查詢也這麼幹)。 請注意這些事情可能在處理一個查詢產生的消息序列的中途發生。

在簡單查詢模式,檢索出來的數值的格式總是文本的, 除非給出的命令是一個從一個聲明了 BINARY 選項的遊標上 FETCH。 在這種情況下,檢索出來的數值是二進制格式的。在 RowDescription 消息裡給出的格式代碼告訴我們用了那種格式。

前端在等待其他類型的消息時必須準備接收 ErrorResponse 和 NoticeResponse 消息。 參閱 Section 44.2.6 後端因為外部的時間可能生成的消息。

我們建議的方法是把前端代碼寫成狀態機的風格,它可以在任何時刻接受任何有意義的信息,而不是寫成假設消息的準確序列的代碼.

44.2.3. 擴展查詢

擴展的查詢協議把上面描述的簡單協議分裂成若幹個步驟。 準備的步驟可以多次復用以提高效率。另外,還可以獲得額外的特性, 比如我們把數據值作為獨立的參數提供的可能性,而不是把它們直接插入一個查詢字串。

在擴展的協議裡,前端首先發送一個 Parse 消息,它包含一個文本查詢字串, 另外還有一些有關參數佔位符的數據類型的信息,以及一個最終準備好的語句對象的名字(一個空字串選擇未命名的準備好的語句)。 響應要麼是一個 ParseComplete 要麼是 ErrorResponse。 參數數據類型可以用 OID 來聲明;如果沒有給出, 那麼分析器將試圖用它對付無類型的字串常量的方法來推導其數據類型。

注意: 在一個 Parse 消息裡包含的查詢字串不能包含超過一個 SQL 語句; 否則就會報告一個語法錯誤。這個限制在簡單查詢協議中並不存在, 但是它存在于擴展的協議中,因為允許準備好的語句或者入口包含多個命令將導致協議過度地復雜。

如果成功創建了一個命名的準備好語句對象,那麼它將持續到當前會話結束, 除非明確刪除。一個未命名的準備好語句只持續到下一個聲明未命名的語句為目標的 Parse 語句發出為止。 (請注意一個簡單的查詢消息也刪除未命名語句。)命名的語句必須明確地關閉,然後才能用一個 Parse 消息重新定義, 但是未命名的語句並不要求這個動作。命名的準備好語句也可以在 SQL 命令級創建和訪問, 方法是使用 PREPAREEXECUTE

只要準備好的語句還存在,那麼我們就可以使用 Bind 消息很容易地使之進入執行狀態。 Bind 消息給出源準備好語句的名字(空字串表示未命名的準備好語句), 目標入口的名字(空字串表示未命名的入口),以及用于那些在準備好的語句中出現的所有參數佔位符的數值。 提供的參數集必須匹配那些準備好的語句需要的東西。Bind 還聲明用于查詢返回的任何數據的格式; 格式可以一次聲明,也可以每個字段進行聲明。響應要麼是 BindComplete 要麼是 ErrorResponse。

注意: 輸出的格式是文本還是二進制是由 Bind 裡給出的格式代碼決定的, 不管用的是什麼 SQL 命令。在使用擴展的查詢協議的時候,遊標聲明裡的 BINARY 屬性是無關的。

如果成功創建了一個入口對象,那麼它將持續到當前事務的結尾, 除非明確刪除。一個未命名的入口在事務的結尾刪除,或者是在發出的下一個 Bind 語句聲明了一個未命名的入口作為目標為止。 (請注意一個簡單查詢效益也會刪除這個未命名的入口。)命名的入口在可以用一個 Bind 消息重新定義之前必須明確關閉, 但是未命名的入口不要求這個動作。命名的入口也可以在 SQL 創建和訪問, 方法是使用 DECLARE CURSORFETCH

只要存在一個入口,那麼就可以用一個 Execute 消息執行它。 Execute 消息聲明入口的名字(空字串表示未命名入口)和一個最大的結果行計數(零表示"抓取所有行")。 結果行計數只對包含返回結果集的入口有意義;在其它情況下,該命令總是執行到結束, 而行計數會被忽略。Execute 可能的響應和那些通過簡單查詢協議發出的查詢一樣, 只不過 Execute 不會導致後端發出 ReadyForQuery。

如果 Execute 在一個入口的執行完成之前終止(因為達到了一個非零的結果行計數), 它將發送一個 PortalSuspended 消息;這個消息的出現告訴前端應該在同一個入口上發出另外一個 Execute 以完成操作。 在入口的執行完成之前,不會發出表示源 SQL 命令結束的 CommandComplete 消息。 因此 Execute 階段總是由下列消息之一出現標志著結束的: CommandComplete,EmptyQueryResponse(如果入口是從一個空字串創建出來的),ErrorResponse,或者 PortalSuspended。

每個擴展查詢消息序列完成後,前端都應該發出一條 Sync 消息。 這個無參數的消息導致後端關閉當前事務──如果當前事務不是在一個BEGIN/COMMIT 事務塊中的話("關閉"的意思就是在沒有錯誤的情況下提交, 或者是有錯誤的情況下回滾)。然後響應一條 ReadyForQuery 消息。 Sync 的目的是提供一個錯誤恢復的重新同步的點。 如果在處理任何擴展查詢消息的時候偵測到任何錯誤,那麼後端發出 ErrorResponse, 然後讀取並拋棄消息,直到一個 sync 的到來,然後發出 ReadyForQuery 並且返回到正常的消息處理中。 (但是要注意如果正在處理 Sync 的時候發生了錯誤,那麼不會忽略任何東西──這樣就保證了為每個 Sync 發出一個並且只是一個的 ReadyForQuery。)

注意: Sync 並不導致一個用 BEGIN 打開的事務塊關閉。 我們可以偵測到這種情況,因為 ReadyForQuery 消息包含事務狀態信息。

除了這些基本的,必須的操作之外,在擴展查詢協議裡還有幾種可選的操作可以使用。

Describe 消息(入口變體)聲明一個現有的入口的名字(或者一個未命名入口就是空字串)。 響應是一個 RowDescription 消息,它描述了執行入口將要返回的行; 或者是一個 NoData 消息──如果入口並不包含會返回行的查詢;或者是一個 ErrorResponse──如果沒有這個入口。

Describe 消息(語句變體)聲明一個現有的準備好語句的名字(如果是一個未命名的準備好語句則是一個空字串)。 響應是一個描述該語句需要的參數的 ParameterDescription 消息, 後面跟著一個描述語句最終執行後返回的行的 RowDescription 消息(或者是 NoData 消息,如果該語句不返回行)。 如果沒有這樣的準備好語句,則返回 ErrorResponse。請注意因為還沒有發出 Bind, 所以後端還不知道用于返回字段的格式;在這種情況下,RowDescription 消息裡面的格式代碼字段將是零。

提示: 在大多數情況下,前端在發出 Execute 之前應該發出某種 Describe 的變體, 以保證它知道如何解析它將得到的結果。

Close 消息關閉一個現有的準備好的語句或者入口,並且釋放資源。 對一個不存在的語句或者入口名字發出 Close 不是一個錯誤。 響應通常是 CloseComplete,但如果在釋放資源的時候發生了一些困難也可以是 ErrorResponse。 請注意關閉一個準備好地語句隱含地關閉任何從該語句構造出來地打開的入口。

Flush 消息並不導致任何特定的輸出的生成, 但是強制後端發送任何還在它的輸出緩衝區中停留的數據。 Flush 必須在除 Sync 外的任何擴展查詢命令後面發出──如果前端希望在發出更多的命令之前檢查該命令的結果的話。 如果不 Flush,後端返回的消息將組合成最小可能的數據包個數,以減少網絡負荷。

注意: 簡單查詢消息大概等于一系列使用未命名的準備好的語句和無參數的入口對象的 Parse,Bind,入口 Describe,Execute,Close,Sync。 一個區別是它會在查詢字串中接受多個 SQL 語句,並在會話中為每個語句自動執行綁定/描述/執行序列。 另外一個區別是它不會返回 ParseComplete,Bindcomplete,CloseComplete,或者 NoData 消息。

44.2.4. 函數調用

Function Call 子協議允許客戶端請求一個對存在于數據庫 pg_proc 系統表中的任意函數的直接調用。客戶端必須在該函數上有執行的權限。

注意: Function Call 子協議是一個遺留的特性,在新代碼裡可能最好避免用它。 類似的結果可以通過設置一個 SELECT function($1, ...) 的準備語句獲得。 這樣 Function Call 循環就可以用 Bind/Execute 代替。

一個函數調用循環是由前端向後端發送一條 FunctionCall 消息初始化的。 然後後端根據函數調用的結果發送一條或者更多響應消息, 並且在最後是一條 ReadyForQuery 響應消息。 ReadyForQuery 通知前端它可以安全地發送一條新的查詢或者函數調用了。

從後端來的可能的響應信息是:

ErrorResponse

發生了一個錯誤。

FunctionCallResponse

函數調用完成並且在消息中返回一個結果。 (請注意 Function Call 協議只能處理單個標量結果,不能處理 rowtype 或者結果集。)

ReadyForQuery

函數調用處理完成。ReadyForQuery 將總是被發送,不管是成功完成處理還是發生一個錯誤。

NoticeResponse

發出了一條有關該函數調用的警告信息。 通知是附加在其他響應上的,也就是說,後端將繼續處理命令。

44.2.5. COPY 操作

COPY 命令允許在服務器和客戶端之間高速的大批量數據傳輸。 拷貝入和拷貝出操作每個都把連接切換到一個獨立的子協議中,並且持續到操作結束。

拷貝入模式(數據傳輸到服務器)是在後端執行一個 COPY FROM STDIN SQL 語句的時候初始化的。 後端發送一個 CopyInResponse 消息給前端。前端應該發送零條或者更多 CopyData 消息,形成一個輸出數據的流。 (消息的邊界和行的邊界沒有任何相關性要求,盡管通常那就是合理的邊界選擇。) 前端可以通過發送一個 CopyDone 消息來終止拷貝入操作(允許成功終止),也可以發出一個 CopyFail 消息(它將導致 COPY SQL 語句帶著錯誤失敗)。 然後後端就恢復回它在 COPY 開始之前的命令處理模式,可能是簡單查詢協議, 也可能是擴展查詢協議。然後它會發送 CommandComplete (如果成功)或者 ErrorResponse (如果失敗)。

如果在拷貝入模式下後端檢測到了錯誤(包括接受接收到 CopyFiail 消息, 或者是任何除了 CopyData 或者 CopyDone 之外的前端消息), 那麼後端將發出一個 ErrorResponse 消息。如果 COPY 命令是通過一個擴展的查詢消息發出的, 那麼後端從現在開始將拋棄前端消息,直到一個 Sync 消息到大,然後它將發出 ReadyForQuery 並且返回到正常的處理中。 如果 COPY 命令是在一個簡單查詢消息裡發出的,那麼該消息剩餘部分被丟棄然後發出 ReadyForQuery 消息。 不管是哪種情況,任何前端發出的 CopyData,CopyDone,或者 CopyFail 消息都將被簡單地拋棄。

拷貝出模式(數據從服務器發出)是在後端執行一個 COPY TO STDOUT SQL 語句的時候初始化的。 後端發出一個 CopyOutResponse 消息給前端,後面跟著零或者多個 CopyData 消息(總是每行一個), 然後跟著 CopyDone。然後後端回退到它在 COPY 開始之前的命令處理模式,然後發送 CommandComplete。 前端不能退出傳輸(除非是關閉連接或者發出一個 Cancel 請求),但是它可以拋棄不需要的 CopyData 和 CopyDone 消息。

在拷貝出模式中,如果後端檢測到錯誤,那麼它將發出一個 ErrorResponse 消息並且回到正常的處理。 前端應該把收到 ErrorResponse(或者實際上除了 CopyData 或者 CopyDone 之外的任何消息類型)當作終止拷貝出模式的標志。

CopyInResponse 和 CopyOutResponse 消息包括告訴前端每行的字段數以及每個字段使用的格式代碼的信息。 (就目前的實現而言,某個 COPY 操作的所有字段都使用同樣的格式,但是消息設計並不做這個假設。)

44.2.6. 異步操作

有幾種情況下後端會發送一些並非由特定的前端的命令流提示的消息。 在任何時候前端都必須準備處理這些信息,即使是並未涉及到查詢的處理的時候。 至少,我們應該在開始讀取查詢響應之前檢查這些情況。

NoticeResponse 消息有可能是因為外部的活動而生成的; 比如,如果數據庫管理員進行一次"快速"數據庫關閉, 那麼後端將在關閉連接之前發送一個 NoticeResponse 來表明這些。 因此,前端應該總是準備接受和顯示 NoticeResponse 消息,即使連接通常是空閒的時候也如此。

如果後端認為前端應該知道的任何參數的活躍數值發生了變化, 那麼都會產生 ParameterStatus 消息。這些最常見發生的地方是前端執行的一個 SET SQL 命令的響應, 並且這個時候實際上是同步 --- 但是也有可能是數據庫管理員改變了配置文件然後 SIGHUP 了 postmaster 導致的參數狀態的變化。 同樣,如果一個 SET 命令回滾,那麼也會生成合適的 ParameterStatus 消息以報告當前有效的數值。

目前,系統內有一套會生成 ParameterStatus 消息的寫成硬代碼的參數: 他們是 server_version(一個啟動後無法修改的偽參數); server_encoding(目前也是啟動後不能改變);client_encodingis_superuser, 和 DateStyle。這些可能在將來改變,或者甚至是變成可以配置的。 因此,前端應該簡單地忽略那些它不懂或者不關心的 ParameterStatus。

如果前端發出一個 LISTEN 命令, 那麼後端將在為同一個通知名執行了 NOTIFY 命令後發送一個 NotificationResponse 消息(不要和 NoticeResponse 混了!)。

注意: 目前,NotificationResponse 只能在一個事務外面發送,因此它將不會在一個命令響應序列中間出現, 但是它可能在 ReadyForQuery 之前出現。不過,在前端邏輯中做上述假設是不明智的。好的做法是在協議的任何點上都可以接受 NotificationResponse。

44.2.7. 取消正在處理的請求

在一條查詢正在處理的時候,可能取消該查詢的處理。 這樣的取消請求不是直接通過打開的連接發送給後端的,這麼做是因為實現的有效性: 我們不希望後端在處理查詢的過程中不停地檢查前端來的輸入。 取消請求應該相對而言比較少見,所以我們把取消做得稍微笨拙一些,以便不影響正常狀況的性能。

要發送一條取消請求,前端打開一個與服務器的新連接並且發送一條 CancelRequest 消息, 而不是通常在新連接中經常發送的 StartupPacket 消息。 服務器將處理這個請求然後關閉連接。 出于安全原因,對取消請求消息不做直接的響應。

除非 CancelRequest 消息包含與連接啟動過程中傳遞給前端的相同的鍵數據(PID 和 安全鍵字), 否則它將被忽略。如果該請求匹配當前運行著的後端的 PID 和安全鍵字, 則退出當前查詢的處理(目前的實現裡採用的方法是向正在處理該查詢的後端進程發送一個特殊的信號。)

取消信號可能有也可能沒有做用 -- 例如,如果它在後端完成查詢的處理後到達, 那麼它就沒有做用。如果取消起作用了,其結果是當前命令帶著一個錯誤信息提前退出。

這麼做是對安全和有效性通盤考慮的結果, 前端沒有直接的方法獲知一個取消請求是否成功。 它必須繼續等待後端對查詢響應。執行取消僅僅是增加了當前查詢快些結束的可能性, 以及增加了當前查詢會帶著一條錯誤信息失敗而不是成功執行的可能性。

因為取消請求是通過新的聯接發送給服務器而不是通過平常的前端/後端通訊鏈接, 所以取消請求可能是任意進程執行的,而不僅僅是要取消查詢的前端。 這樣可能對創建多進程應用有某種靈活性的好處。但是同時這樣也帶來了安全風險, 因為這樣任何一個非認證用戶都可能試圖取消查詢。 這個安全風險通過要求在取消請求中提供一個動態生成的安全鍵字排除。

44.2.8. 終止

通常的終止過程的優雅方法是前端發送一條 Terminate (終止)消息並且立刻關閉聯接。 一旦收到消息,後端馬上關閉聯接並且退出。

在少數情況下(比如一個管理員命令數據庫關閉),後端可能在沒有任何前端請求的情況下斷開連接。 在這種情況下,後端將在它斷開連接之前嘗試發送一個錯誤或者通知信息,給出斷開的原因。

其它終止的情況發生在各種失效的場合,比如某一方的內核轉儲,失去通訊鏈路, 丟失了消息邊界同步等。不管是前端還是後端看到了一個意外的連接關閉,那麼它應該清理現場並且終止。 如果前端不想終止自己,那麼它可以通過替換服務器的方法重啟一個新的後端。 如果收到了一個無法識別的消息,那麼我們也建議關閉連接,因為出現這種情況可能意味著是丟失了消息邊界的同步。

不管是正常還是不正常的終止,任何打開的事務都會回滾,而不是提交。 不過,我們應該注意的是如果一個前端在一個查詢正在處理的時候斷開, 那麼後端很可能在注意到斷開之前先完成查詢的處理。 如果查詢處于任何事務塊之外(BEGIN ... COMMIT 序列),那麼其結果很可能在得知斷開之前被提交。

44.2.9. SSL 會話加密

如果制作 PostgreSQL 的時候打開了 SSL 支持,那麼前後端通訊就可以用 SSL 加密。 這樣就提供了一種在攻擊者可能捕獲會話通訊數據包的環境下保證通訊安全的方法。

要開始一次 SSL 加密聯接,前端先是發送一個 SSLRequest 消息,而不是 StartupMessage。然後服務器以一個包含 SN 的字節響應,分別表示它願意還是不願意進行 SSL。如果前端對響應不滿意, 那麼它可以關閉聯接。要在 S 之後繼續,那麼先進行與服務器的 SSL 啟動握手(沒有在這裡描述,是 SSL 規範的一部分)。 如果這些成功了,那麼繼續發送普通的 StartupMessage。這種情況下, StartupMessage 和所有隨後的數據都將由 SSL 加密。要在 N 之後繼續,則發送普通的 StartupMessage 然後不帶加密進行處理。

前端應該也準備處理一個來自服務器的給 SSLRequest 的 ErrorMessage 響應。這種情況只有在服務器給 PostgreSQL 的 SSL 支持增加了附加的期望的情況下才會出現。 在這種情況下,聯接必需關閉,但是前端可以選擇打開一個新的聯接然後不帶 SSL 進行聯接。

一個初始化的 SSLRequest 也可以用于打開來用于發送一條 CancelRequest 消息的聯接中。

如果協議本身並未提供某種方法強制 SSL 加密,那麼管理員可以把服務器配置為拒絕未加密的會話,這是認證檢查的一個副產品。