偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

PostgreSQL客戶端處理事務(wù)功能詳解

數(shù)據(jù)庫 其他數(shù)據(jù)庫 數(shù)據(jù)庫運(yùn)維 PostgreSQL
在這里我們將討論的是PostgreSQL客戶端處理事務(wù)功能,希望通過本文能對(duì)大家了解PostgreSQL有所幫助。

PostgreSQL所針對(duì)的目標(biāo),與目前使用MySQL數(shù)據(jù)庫的人群很接近。那么究竟PostgreSQL有何優(yōu)勢?本文將為大家做出解釋。

本文將介紹PostgreSQL的事務(wù)處理功能的基本概念,并講解如何通過PostgreSQL客戶端以及從PHP腳本內(nèi)部來執(zhí)行各種事務(wù)。通過本文,您將學(xué)習(xí)什么是事務(wù),PostgreSQL是如何實(shí)現(xiàn)它們的,以及怎樣在自己的PHP應(yīng)用程序中如何使用事務(wù)。

一、什么是事務(wù)?

事務(wù)可以看作是一個(gè)數(shù)據(jù)庫操作的有序集,這些操作應(yīng)作為整體來對(duì)待,即集內(nèi)所有的操作都成功的時(shí)候,該事務(wù)才被認(rèn)為是成功的,否則的話,即使其中只有一個(gè)操作失敗,該事務(wù)也會(huì)被認(rèn)為是不成功。如果所有的操作全部成功,那么事務(wù)就會(huì)被提交,這時(shí)它的所作的修改才能被所有其他數(shù)據(jù)庫進(jìn)程所用。如果操作失敗,該事務(wù)就會(huì)被回滾,同時(shí)事務(wù)內(nèi)部所有已完成操作所做的修改會(huì)被全部撤銷。在事務(wù)提交之前,一次事務(wù)期間所作的修改,只對(duì)擁有此事務(wù)的進(jìn)程可用。之所以這樣做,是為了防止其他線程使用了事務(wù)修改的數(shù)據(jù)后,事務(wù)隨后又發(fā)生了回滾,從而導(dǎo)致數(shù)據(jù)完整性錯(cuò)誤。

#T#

事務(wù)功能是企業(yè)數(shù)據(jù)庫的關(guān)鍵所在,因?yàn)樵S多業(yè)務(wù)流程是由多步組成的,下面我們以在線購物為例進(jìn)行說明。在結(jié)帳時(shí),顧客的購物車會(huì)跟現(xiàn)有庫存進(jìn)行比對(duì),以確保有現(xiàn)貨。接下來,顧客必須提供收費(fèi)與交貨信息,這時(shí)就需要檢查相應(yīng)的信用卡是否可用,并從中扣款。然后,需要從產(chǎn)品庫存清單中扣除相應(yīng)的數(shù)量,如果庫存不足,還應(yīng)向采購部門發(fā)出通知。在這些步驟中,只要有一步發(fā)生錯(cuò)誤,那么所有修改都不應(yīng)該生效。假設(shè)沒有現(xiàn)貨的情況下,還是從顧客的信用卡中扣了款的話,那么顧客會(huì)很生氣,問題就會(huì)很嚴(yán)重了。同樣地,作為在線商家,當(dāng)信用卡無效的時(shí)候,您也肯定不希望從存貨清單中扣除此次顧客選擇的商品數(shù)量,或者因此而發(fā)出相應(yīng)的采購?fù)ㄖ?/p>

我們這里所說的事務(wù),必須滿足四大要件:

原子性:事務(wù)所有的步驟必須全部成功;否則,任何步驟都不會(huì)被提交。

一致性:事務(wù)所有的步驟必須全部成功;否則,所有的數(shù)據(jù)都會(huì)恢復(fù)到事務(wù)開始之前的狀態(tài)。

隔離性:在事務(wù)完成之前,所有已執(zhí)行的步驟必須與系統(tǒng)保持隔離。

持久性:所有提交的數(shù)據(jù),系統(tǒng)必須加以恰當(dāng)保存,并保證萬一系統(tǒng)發(fā)生故障時(shí)仍能將數(shù)據(jù)恢復(fù)到有效狀態(tài)。

PostgreSQL的事務(wù)支持功能完全遵循上述四項(xiàng)基本原則(有時(shí)候人們簡稱為ACID),從而能夠有效保證數(shù)據(jù)庫的完整性。

二、PostgreSQL的事務(wù)隔離

PostgreSQL的事務(wù)支持是通過通常所說的多版本并發(fā)控制或者M(jìn)VCC方法實(shí)現(xiàn)的,也就是說,每當(dāng)事務(wù)進(jìn)行處理時(shí),它看到的是自己的數(shù)據(jù)庫快照,而非底層數(shù)據(jù)的實(shí)際狀態(tài)。 這使得任何給定的事務(wù)無法看到其它已經(jīng)啟動(dòng)但是尚未提交的事務(wù)對(duì)數(shù)據(jù)所作的部分修改。這項(xiàng)原則就是所謂的事務(wù)隔離。

SQL標(biāo)準(zhǔn)規(guī)定了三種屬性以用來確定一個(gè)事務(wù)處于四級(jí)隔離級(jí)別的哪一級(jí),這些屬性如下所示:

臟讀:一個(gè)事務(wù)讀取了另一個(gè)未提交的并行事務(wù)寫的數(shù)據(jù)

不可重復(fù)讀:當(dāng)一個(gè)事務(wù)重新讀取前面讀取過的數(shù)據(jù)時(shí),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù)修改過

幻讀:一個(gè)事務(wù)重新執(zhí)行一個(gè)查詢時(shí),返回一套符合查詢條件的行,發(fā)現(xiàn)這些行因?yàn)槠渌罱峤坏氖聞?wù)而發(fā)生了改變

這三種情況確定了一個(gè)事務(wù)的隔離級(jí)別,所有四種水平如表1所示。

表1 SQL標(biāo)準(zhǔn)事務(wù)隔離級(jí)別

SQL標(biāo)準(zhǔn)事務(wù)隔離級(jí)別

PostgreSQL允許您請(qǐng)求四種可能的事務(wù)隔離級(jí)別中的任意一種。但是在內(nèi)部,實(shí)際上只有兩種可用的隔離級(jí)別,分別對(duì)應(yīng)讀已提交和可串行化。如果你選擇了讀未提交的級(jí)別,實(shí)際上你用的是讀已提交,在你選擇可重復(fù)的讀級(jí)別的時(shí)候,實(shí)際上你用的是可串行化,所以實(shí)際的隔離級(jí)別可能比你選擇的更嚴(yán)格。雖然這看起來是有悖于我們的直覺,但是SQL標(biāo)準(zhǔn)的確允許這樣做,因?yàn)樗姆N隔離級(jí)別只定義了哪種現(xiàn)象不能發(fā)生,但是沒有定義那種現(xiàn)象一定發(fā)生,所以除了不允許的事務(wù)特性之外,所有的特性都是允許的。舉例來說,如果您請(qǐng)求可重復(fù)讀模式,那么該標(biāo)準(zhǔn)只是要求您不準(zhǔn)臟讀以及不可重讀,但是卻沒有要求允許幻讀。因此,可串行化事務(wù)模式滿足可重復(fù)讀模式的要求,即使它跟定義沒有完全吻合。因此,您應(yīng)當(dāng)確切的知道,當(dāng)您請(qǐng)求讀未提交模式的時(shí)候,您實(shí)際得到的卻是讀已提交模式;而當(dāng)您請(qǐng)求可重復(fù)讀的時(shí)候,實(shí)際得到的是可串行化模式。您還應(yīng)當(dāng)意識(shí)到,默認(rèn)情況下,如果您沒有請(qǐng)求一個(gè)特定的隔離級(jí)別,那么您得到的將是讀已提交隔離級(jí)別。

下面我們了解一下讀已提交和可串行化之間的主要區(qū)別。在讀已提交模式下SELECT 查詢只能看到該查詢開始之前提交的數(shù)據(jù)而永遠(yuǎn)無法看到未提交的數(shù)據(jù)或者是在查詢執(zhí)行時(shí)其他并行的事務(wù)提交的改變;不過 SELECT 的確看得見同一次事務(wù)中前面更新的結(jié)果,即使它們還沒提交也看得到。實(shí)際上,一個(gè) SELECT 查詢看到一個(gè)在該查詢開始運(yùn)行的瞬間該數(shù)據(jù)庫的一個(gè)快照。請(qǐng)注意兩個(gè)相鄰的 SELECT 命令可能看到不同的數(shù)據(jù),哪怕它們是在同一個(gè)事務(wù)里,因?yàn)槠渌聞?wù)會(huì)在第一個(gè)SELECT執(zhí)行的時(shí)候提交。當(dāng)一個(gè)事務(wù)處于可串行化級(jí)別的時(shí)候,一個(gè) SELECT 查詢只能看到在該事務(wù)開始之前提交的數(shù)據(jù)而永遠(yuǎn)看不到未提交的數(shù)據(jù)或事務(wù)執(zhí)行中其他并行事務(wù)提交的修改;不過,SELECT 的確看得到同一次事務(wù)中前面的更新的效果,即使事務(wù)還沒有提交也一樣。這個(gè)行為和讀已提交級(jí)別是不太一樣,它的 SELECT 看到的是該事務(wù)開始時(shí)的快照,而不是該事務(wù)內(nèi)部當(dāng)前查詢開始時(shí)的快照。這樣,一個(gè)事務(wù)內(nèi)部后面的SELECT命令總是看到同樣的數(shù)據(jù)。這意味著,讀已提交模式下一個(gè)事務(wù)內(nèi)部后面的SELECT命令可以看到不同的數(shù)據(jù),但是在可串行化模式下卻總是看到同樣的數(shù)據(jù)。

對(duì)于以上區(qū)別,請(qǐng)讀者一定弄清楚。雖然剛看上去有些復(fù)雜,但是只要抓住兩個(gè)要點(diǎn),理解起來還是很容易的:首先,PostgreSQL運(yùn)行事務(wù)的并發(fā)運(yùn)行,也就是說一個(gè)事務(wù)執(zhí)行的時(shí)候,并不妨礙另一事務(wù)對(duì)相同數(shù)據(jù)操作。其次,一定注意快照的概念,事務(wù)提交前操作的是數(shù)據(jù)快照而非數(shù)據(jù)庫本身,同時(shí)注意不同隔離級(jí)別使用的是何時(shí)的快照——事務(wù)開始之前的快照,還是事務(wù)內(nèi)部操作開始之前的快照?我想只要抓住了以上要點(diǎn),我們就能很好的把握各種隔離級(jí)別之間的區(qū)別了。

上面介紹了事務(wù)的基本概念,接下來我們開始演示如何在PostgreSQL客戶端中使用事務(wù)。

三、創(chuàng)建示例表

下面,我們通過一個(gè)具體的在線交易應(yīng)用為例來闡述上面介紹的事務(wù)概念。為此,我們需要先給這個(gè)示例程序在名為company的數(shù)據(jù)庫中創(chuàng)建兩個(gè)表:participant和trunk。同時(shí),我們還會(huì)介紹各個(gè)表的用途和結(jié)構(gòu)。建好表后,我們還需為它們填入一些樣本數(shù)據(jù),具體如下所示。

我們首先創(chuàng)建Participant表,這個(gè)表用來存放參與物品交換者的信息,包括他們的姓名、電子郵件地址和可用現(xiàn)金:

  1. CREATE TABLE participant (  
  2. participantid SERIAL,  
  3. name TEXT NOT NULL,  
  4. email TEXT NOT NULL,  
  5. cash NUMERIC(5,2) NOT NULL,  
  6. PRIMARY KEY (participantid)  
  7.  );  
  8. CREATE TABLE participant (  
  9. participantid SERIAL,  
  10. name TEXT NOT NULL,  
  11. email TEXT NOT NULL,  
  12. cash NUMERIC(5,2) NOT NULL,  
  13. PRIMARY KEY (participantid)  
  14.  ); 

然后,我們開始創(chuàng)建trunk 表。這個(gè)表存儲(chǔ)參與者所有的物品的有關(guān)信息,包括屬主、名稱、描述和價(jià)格:

  1. CREATE TABLE trunk (  
  2. trunkid SERIAL,  
  3. participantid INTEGER NOT NULL REFERENCES participant(participantid),  
  4. name TEXT NOT NULL,  
  5. price NUMERIC(5,2) NOT NULL,  
  6. description TEXT NOT NULL,  
  7. PRIMARY KEY (trunkid)  
  8. ); 

用到的表都建好了,下面我們開始添加樣本數(shù)據(jù)。為簡單起見,我們這里只添加了兩名參與者,即Tom和Jack;并為trunks表添加了少量的物品,如下所示:

  1.  INSERT INTO participant (name,email,cash) VALUES 
  2. ('Tom','Tom@example.com','1100.00');  
  3. INSERT INTO participant (name,email,cash) VALUES 
  4. ('Jack','Jack@example.com','1150.00');  
  5.  INSERT INTO trunk (participantid,name,price,description) VALUES 
  6.  (1,'Linux CD','1.00','Complete OS on a CD'); INSERT INTO trunk (participantid,  
  7.  name,price,description) VALUES 
  8.  (2,'ComputerABC','12.99','a book about computer!');  
  9.  INSERT INTO trunk (participantid,name,price,description) VALUES 
  10.  (2,'Magazines','6.00','Stack of Computer Magazines'); 
四、簡單的示例應(yīng)用

為了讓讀者切身體會(huì)事務(wù)的運(yùn)行機(jī)制,我們從命令行來運(yùn)行我們的示例程序。我們的示例程序?qū)⒀菔緝蓚€(gè)交易者如何通過現(xiàn)金的形式來互換物品。在考察代碼之前,先讓我們看一下更容易理解的偽代碼:

1. 參加者Tom請(qǐng)求一個(gè)物品,例如位于參加者Jack的虛擬儲(chǔ)物箱中的ComputerABC。

2. 參加者Tom向參加者Jack的帳戶上劃過去$12.99的現(xiàn)金。結(jié)果是,Tom的帳戶中現(xiàn)金數(shù)量減去12.99,而Jack的帳戶的現(xiàn)金數(shù)量則增加12.99。

3. 將ComputerABC的屬主改為參加者Tom。

如您所見,這個(gè)過程中的每一步對(duì)于該交易的整體成功來說都是非常關(guān)鍵的,所以必須保證我們的數(shù)據(jù)不會(huì)由于單步失敗而遭到破壞。當(dāng)然,現(xiàn)實(shí)中的情景要比這里復(fù)雜得多,例如必須檢查購買方是否具有足夠的現(xiàn)金等等,不過為了簡單起見,我們忽略了一些細(xì)節(jié),以便讀者將主要精力都放到事務(wù)這一主題上來。

我們可以提交START TRANSACTION命令來啟動(dòng)事務(wù)處理:

  1. company=# START TRANSACTION;  
  2. START TRANSACTION 

注意,START TRANSACTION還有一個(gè)別名,即BEGIN命令,雖然兩者都能完成該任務(wù),但是我們還是推薦您使用后者,因?yàn)樗蟂QL規(guī)范。接下來,從Tom的帳戶中扣除$12.99:

  1. company=# UPDATE participant SET cash=cash-12.99 WHERE participantid=1;  
  2. UPDATE 1 

然后,為Jack的帳戶增加$12.99:

  1. company=# UPDATE participant SET cash=cash+12.99 WHERE participantid=2;  
  2. UPDATE 1 

然后,將ComputerABC過戶給Tom:

  1. company=# UPDATE trunk SET participantid =1 WHERE name='ComputerABC' AND 
  2. company-# participantid=2;  
  3. UPDATE 1 

現(xiàn)在,我們已經(jīng)完成了一筆交易,接下來我們開始介紹PostgreSQL的另一個(gè)特性:savepoint。注意,Savepoint功能是從PostgreSQL 8.0.0才引入的,因此如果您使用的是該版本之前的PostgreSQL的話,那么就無法使用下面介紹的命令。Savepoint就像是事務(wù)的書簽,我們可以在一個(gè)事務(wù)里設(shè)置一個(gè)點(diǎn),以便萬一事務(wù)出錯(cuò)時(shí)回滾到該保存點(diǎn)。我們可以像下面這樣提交一個(gè)保存點(diǎn):

  1. company=# SAVEPOINT savepoint1;  
  2. SAVEPOINT 

提交了保存點(diǎn)后,我們就可以繼續(xù)執(zhí)行各種語句了。為了演示保存點(diǎn)的功能,假如我們想要檢驗(yàn)對(duì)participant表所做的修改,但是在查詢命令中拼錯(cuò)了participant表的名稱:

  1. company=# SELECT * FROM particapant;  
  2. ERROR: relation "particapant" does not exist 

注意,對(duì)于8.0.0版本之前的PostgreSQL來說,則必須回滾整個(gè)事務(wù)。如果我們沒有設(shè)置保存點(diǎn)就執(zhí)行了這個(gè)查詢,那么我們就會(huì)因?yàn)槭聞?wù)中的單個(gè)錯(cuò)誤而不得不回滾整個(gè)事務(wù)。即使我們改正了這個(gè)錯(cuò)誤,PostgreSQL也不會(huì)讓我們繼續(xù)該事務(wù):

  1. company=# SELECT * FROM participant;  
  2. ERROR: current transaction is aborted, commands ignored until end of transaction block 

然而,因?yàn)槲覀円呀?jīng)提交了一個(gè)保存點(diǎn),所以我們可以回滾到這個(gè)保存點(diǎn),也就是說使我們的事務(wù)回到出錯(cuò)之前的狀態(tài):

  1. company=# ROLLBACK TO savepoint1;  
  2. ROLLBACK 

注意,拼寫錯(cuò)誤是一個(gè)非常煩人的問題,不過對(duì)于PostgreSQL 8.1來說,客戶端psql帶有一個(gè)\reseterror選項(xiàng),能夠自動(dòng)地設(shè)置保存點(diǎn),并在出錯(cuò)時(shí)進(jìn)行回滾。

我們現(xiàn)在可以在我們的事務(wù)之內(nèi)進(jìn)行查詢了,好象根本發(fā)生錯(cuò)誤一樣。下面我們花一些時(shí)間來檢查participant表,以保證向借方和貸方記入正確的現(xiàn)金數(shù)量。

  1. company=# SELECT * FROM participant; 

將返回:

  1. participantid | name | email | cash  
  2. ---------------+--------+--------------------+--------  
  3. 1 | Tom | Tom@example.com | 1087.01  
  4. 2 | Jack | Jack@example.com | 1162.99  
  5. (2 rows

此外,我們還需要檢查一下trunk表,看看ComputerABC的屬主已經(jīng)是否進(jìn)行了相應(yīng)的修改。然而需要注意的是,由于PostgreSQL強(qiáng)制執(zhí)行ACID原則,因此這個(gè)改變只對(duì)執(zhí)行該事務(wù)的當(dāng)前連接可用。為了說明這一點(diǎn),我們啟動(dòng)另一個(gè)psql客戶端,并再次登陸數(shù)據(jù)庫company,查看participant表時(shí),我們會(huì)發(fā)現(xiàn)交易雙方相應(yīng)的現(xiàn)金值并沒有變。這是因?yàn)锳CID中的隔離性所導(dǎo)致的。除非我們提交了所作的修改,否則其他連接是看不到事務(wù)處理過程中所作的任何改變的。

如果想撤銷事務(wù)該怎么操作呢?回到第一個(gè)客戶端窗口,并通過ROLLBACK命令取消這些改變:

  1. company=# ROLLBACK;  
  2. ROLLBACK 

現(xiàn)在,再一次執(zhí)行SELECT命令:

  1. company=# SELECT * FROM participant;  
  2. This returns:  
  3. CHAPTER  
  4.  
  5. participantid | name | email | cash  
  6. ---------------+--------+--------------------+--------  
  7. 1 | Tom | Tom@example.com | 1100.00  
  8. 2 | Jack | Jack@example.com | 1150.00  
  9. (2 rows

需要注意的是,交易雙方的現(xiàn)金量已經(jīng)恢復(fù)為原始值。檢查trunk表還會(huì)看到ComputerABC的屬主也沒有任何變化。再次重復(fù)前面的過程,這一次通過使用COMMIT命令而不是通過回滾操作來提交改變。一旦提交事務(wù),再次返回到第二個(gè)客戶端并查看這兩個(gè)數(shù)據(jù)表,您會(huì)發(fā)現(xiàn)提交的變化已經(jīng)可用了。

需要說明的是,COMMIT或者ROLLBACK命令提交之前,事務(wù)處理之間對(duì)數(shù)據(jù)所作的任何修改都不會(huì)生效。這意味著,如果PostgreSQL服務(wù)器在提交這些修改之前崩潰的話,那么這些修改也不會(huì)發(fā)生;要想使這些修改發(fā)生的話,您必須重新啟動(dòng)該事務(wù)。

五、小結(jié)

本文中,我們介紹了PostgreSQL的事務(wù)功能,并講解如何通過PostgreSQL客戶端使用事務(wù)。讀者通過閱讀本文,將會(huì)學(xué)習(xí)什么是事務(wù),PostgreSQL是如何實(shí)現(xiàn)它們的。在后面一篇文章中,我們將介紹如何在自己的PHP應(yīng)用程序中如何使用事務(wù)。

【編輯推薦】

  1. PostgreSQL 8.4發(fā)布 新增查詢監(jiān)控工具
  2. PostgreSQL新版提高Oracle兼容性 欲與甲骨文試比高?
  3. 細(xì)化解析PostgreSQL的昨天今天和明天
  4. InnoDB還是MyISAM 再談MySQL存儲(chǔ)引擎的選擇
  5. 淺談MySQL存儲(chǔ)引擎選擇 InnoDB還是MyISAM
責(zé)任編輯:彭凡 來源: ITPUB
相關(guān)推薦

2010-03-18 15:44:22

VSTS 2010VS 2010

2010-05-12 15:46:51

Subversion客

2022-06-02 10:38:42

微服務(wù)數(shù)據(jù)源分布式

2009-03-04 10:27:50

客戶端組件桌面虛擬化Xendesktop

2020-04-23 09:32:33

zookeeperCP系統(tǒng)

2010-04-08 15:35:13

Oracle 簡易客戶

2009-07-24 17:31:56

ASP.NET AJA

2010-05-31 15:55:42

2013-06-08 09:59:15

VMwarevSphere Web

2010-03-18 16:49:43

Java Socket

2010-06-01 14:11:11

TortoiseSVN

2009-12-22 10:29:59

WCF客戶端處理

2009-08-21 16:14:52

服務(wù)端與客戶端通信

2021-04-30 08:19:32

SpringCloud客戶端負(fù)載Ribbo

2010-09-29 15:05:44

DHCP客戶端故障

2010-02-24 16:39:27

WCF客戶端處理

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2011-08-17 10:10:59

2024-12-02 09:19:44

2022-01-20 16:31:41

AndroidTwitter客戶端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)