事務和鎖(SQLite)

來源:互聯網
上載者:User

轉自:http://www.sqlite.com.cn/MySqlite/4/539.Html

 

2、    事務(Transaction)

2.1、事務的周期(Transaction Lifecycles)


序與事務之間有兩件事值得注意:
(1)    哪些對象在事務下運行——這直接與API有關。
(2)  
 事務的生命週期,即什麼時候開始,什麼時候結束以及它在什麼時候開始影響別的串連(這點對於並發性很重要)——這涉及到SQLite的具體實現。

個串連(connection)可以包含多個(statement),而且每個串連有一個與資料庫關聯的B-tree和一個pager。Pager在串連
中起著很重要的作用,因為它管理事務、鎖、記憶體緩衝以及負責崩潰恢複(crash
recovery)。當你進行資料庫寫操作時,記住最重要的一件事:在任何時候,只在一個事務下執行一個串連。這些回答了第一個問題。
一般來說,
一個事務的生命和statement差不多,你也可以手動結束它。預設情況下,事務自動認可,當然你也可以通過BEGIN..COMMIT手動提交。接下
來就是鎖的問題。

2.2、鎖的狀態(Lock States)


對於實現並發訪問很重要,而對於大型通用的DBMS,鎖的實現也十分複雜,而SQLite相對較簡單。通常情況下,它的期間和事務一致。一個事務開
始,它會先加鎖,事務結束,釋放鎖。但是系統在事務沒有結束的情況下崩潰,那麼下一個訪問資料庫的串連會處理這種情況。
在SQLite中有5種不
同狀態的鎖,串連(connection)任何時候都處於其中的一個狀態。顯示了相應的狀態以及鎖的生命週期。

關於這個圖有以下幾點
值得注意:
(1)  
 一個事務可以在UNLOCKED,RESERVED或EXCLUSIVE三種狀態下開始。預設情況下在UNLOCKED時開始。
(2)  
 白色框中的UNLOCKED, PENDING, SHARED和 RESERVED可以在一個資料庫的同一時存在。
(3)  
 從灰色的PENDING開始,事情就變得嚴格起來,意味著事務想得到排斥鎖(EXCLUSIVE)(注意與白色框中的區別)。
雖然鎖有這麼多狀
態,但是從體質上來說,只有兩種情況:讀事務和寫事務。

2.3、讀事務(Read
Transactions)

我們先來看看SELECT語句執行時鎖的狀態變化過程,非常簡單:一個串連執行select語句,觸
發一個事務,從UNLOCKED到SHARED,當事務COMMIT時,又回到UNLOCKED,就這麼簡單。
考慮下面的例子(為了簡單,這裡用
了偽碼):
db = open('foods.db')
db.exec('BEGIN')
db.exec('SELECT
* FROM episodes')
db.exec('SELECT * FROM episodes')
db.exec('COMMIT')
db.close()


於顯式的使用了BEGIN和COMMIT,兩個SELECT命令在一個事務下執行。第一個exec()執行時,connection處於SHARED,然
後第二個exec()執行,當事務提交時,connection又從SHARED回到UNLOCKED狀態,如下:
UNLOCKED→PENDING→SHARED→UNLOCKED

果沒有BEGIN和COMMIT兩行時如下:
UNLOCKED→PENDING→SHARED→UNLOCKED→PENDING→
SHARED→UNLOCKED

2.4、寫事務(Write
Transactions)

下面我們來考慮寫資料庫,比如UPDATE。和讀事務一樣,它也會經曆
UNLOCKED→PENDING→SHARED,但接下來卻是灰色的PENDING,

2.4.1、The Reserved States

當一個串連(connection)向資料庫寫資料時,從
SHARED狀態變為RESERVED狀態,如果它得到RESERVED鎖,也就意味著它已經準備好進行寫操作了。即使它沒有把修改寫入資料庫,也可以把
修改儲存到位於pager中緩衝中(page cache)。
當一個串連進入RESERVED狀態,pager就開始初始化恢複日誌
(rollback journal)。在RESERVED狀態下,pager管理著三種頁面:
(1)    Modified
pages:包含被B-樹修改的記錄,位於page cache中。
(2)    Unmodified
pages:包含沒有被B-tree修改的記錄。
(3)    Journal pages:這是修改頁面以前的版本,這些並不儲存在page
cache中,而是在B-tree修改頁面之前寫入日誌。
Page
cache非常重要,正是因為它的存在,一個處於RESERVED狀態的串連可以真正的開始工作,而不會干擾其它的(讀)串連。所以,SQLite可以高
效的處理在同一時刻的多個讀串連和一個寫串連。

2.4.2 、The
Pending States

當一個串連完成修改,就真正開始提交事務,執行該過程的pager進入EXCLUSIVE狀態。從
RESERVED狀態,pager試著擷取 PENDING鎖,一旦得到,就獨佔它,不允許任何其它串連獲得PENDING鎖(PENDING is a
gateway
lock)。既然寫操作持有PENDING鎖,其它任何串連都不能從UNLOCKED狀態進入SHARED狀態,即沒有任何串連可以進入資料(no
new readers, no new
writers)。只有那些已經處於SHARED狀態的串連可以繼續工作。而處於PENDING狀態的Writer會一直等到所有這些串連釋放它們的鎖,
然後對資料庫加EXCUSIVE鎖,進入EXCLUSIVE狀態,獨佔資料庫(討論到這裡,對SQLite的加鎖機制應該比較清晰了)。

2.4.3、The Exclusive State

在EXCLUSIVE狀態下,主
要的工作是把修改的頁面從page cache寫入資料庫檔案,這是真正進行寫操作的地方。
在pager寫入modified
pages之前,它還得先做一件事:寫日誌。它檢查是否所有的日誌都寫入了磁碟,而這些通常位於操作的緩衝區中,所以pager得告訴OS把所有的檔案寫
入磁碟,這是由程式synchronous(通過調用OS的相應的API實現)完成的。
日誌是資料庫進行恢複的惟一方法,所以日誌對於DBMS非
常重要。如果日誌頁面沒有完全寫入磁碟而發生崩潰,資料庫就不能恢複到它原來的狀態,此時資料庫就處於不一致狀態。日誌寫入完成後,pager就把所有的
modified pages寫入資料庫檔案。接下來就取決於事務提交的模式,如果是自動認可,那麼pager清理日誌,page
cache,然後由EXCLUSIVE進入UNLOCKED。如果是手動提交,那麼pager繼續持有EXCLUSIVE鎖和儲存日誌,直到COMMIT
或者ROLLBACK。

總之,從效能方面來說,進程佔有排斥鎖的時間應該儘可能的短,所以DBMS通常都是在真正寫檔案時才會佔有排斥
鎖,這樣能大大提高並發效能。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.