如何併發的訪問資料庫呢?答案就是加鎖。
接下來說一下,資料庫的鎖機制,資料庫中都有哪些鎖?
首先呢,鎖是一種併發控制技術,鎖是用來在多個使用者同時訪問同乙個資料的時候保護資料的。
有2種基本的鎖型別:
共享(s)鎖:多個事務可封鎖乙個共享頁;任何事務都不能修改該頁;通常是該頁被讀取完畢,s鎖立即被釋放。在執行select語句的時候需要給操作物件(表或一些記錄)加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖(乙個物件上可以加n個共享鎖),否則不行。共享鎖通常在執行完select語句之後被釋放,當然也可能是在事務結束(包括正常結束和異常結束)的時候被釋放,主要取決與資料庫所設定的事務隔離級別。
排它(x)鎖:僅允許乙個事務封鎖此頁;其他任何事務必須等到x鎖被釋放才能對該頁進行訪問;x鎖一直到事務結束才能被釋放。執行insert、update、delete語句的時候需要給操作的物件加排它鎖,在加排他鎖之前必須確認該物件上沒有其他任何鎖,一旦加上排它鎖之後,就不能再給這個物件加其他任何鎖。排它鎖的釋放通常是在事務結束的時候(當然也有例外,就是在資料庫事務隔離級別被設定為read uncommitted(讀未提交資料)的時候,這種情況下排他鎖會在執行完更新操作之後被釋放,而不是在事務結束的時候)。
按鎖的機制
既然使用了鎖,就有出現死鎖的可能。
產生死鎖的四個必要條件:
互斥條件:乙個資源每次只能被乙個程序使用。
請求與保持條件:乙個程序因請求資源而阻塞時,對已獲得的資源保持不放。
不可剝奪條件:程序已獲得的資源,在未使用完之前,不能強行剝奪。
環路等待條件:若干個程序之間形成一種頭尾相接的迴圈等待資源關係。
只要系統發生了死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
預防死鎖
預防死鎖的發生只需要破壞死鎖產生的四個必要條件之一即可。
1)破壞互斥條件
如果允許系統資源都能共享使用,則系統不會進入死鎖狀態。但有些資源根本不能同時訪問,如印表機等臨界資源只能互斥使用。所以破壞互斥條件而預防死鎖的方法不太可行,而且在有些場合應該保護這種互斥性。
2)破壞不可剝奪條件
當乙個已保持了某些不可剝奪資源的程序,請求新的資源而得不到滿足時,它必須釋放已經保持的所有資源,待以後需要時再重新申請。這意味著,乙個程序已占有的資源會被暫時釋放,或者說是被剝奪了,或從而破壞了不可剝奪條件。
該策略實現起來比較複雜,釋放已獲得的資源可能造成前一階段工作的失效,反覆地申請和釋放資源會增加系統開銷,降低系統吞吐量。這種方法常用於狀態易於儲存和恢復的資源,如cpu的暫存器及記憶體資源,一般不能用於印表機之類的資源。
3)破壞請求和保持的條件
採用預先靜態分配方法,即程序在執行前一次申請完它所需要的全部資源,在它的資源為滿足前,不把它投入執行。一旦投入執行後,這些資源就一直歸它所有,也不再提出其他資源請求,這樣就可以保證系統不會發生死鎖。
這種方式實現簡單,但缺點也顯而易見,系統資源被嚴重浪費,其中有些資源可能僅在執行初期或執行快結束時才使用,甚至根本不使用。而且還會導致「飢餓」現象,當由於個別資源長期被其他程序占用時,將致使等待該資源的程序遲遲不能開始執行。
4)破壞環路等待條件
為了破壞環路等待條件,可採用順序資源分配法。首先給系統中的資源編號,規定每個程序,必須按編號遞增的順序請求資源,同類資源一次申請完。也就是說,只要程序提出申請分配資源ri,則該程序在以後的資源申請種,只能申請編號大於ri的資源。
這種方法存在的問題時,編號必須相對穩定,這就限制了新型別裝置的增加;儘管在為資源編號時已考慮到大多數作業實際使用這些資源的順序,但也經常會發生作業使用資源的順序與系統規定順序不同的情況,造成資源的浪費;此外,這種按規定次序申請資源的方法,也必然會給使用者的程式設計帶來麻煩。
解除死鎖
1)從死鎖程序處剝奪資源;
2)終止部分或全部程序;
mysql鎖的粒度(即鎖的級別)
mysql各儲存引擎使用了三種型別(級別)的鎖定機制:行級鎖定、頁級鎖定和表級鎖定。
1、表級鎖:直接鎖定整張表,在你鎖定期間,其他程序無法對該錶進行寫操作。如果你是寫鎖,則其他程序則讀也不允許。特點:開銷小,加鎖快;不會出現死鎖;鎖粒度最大,發生鎖衝突的概率最高,併發度最低。
myisam儲存引擎採用的是表級鎖。
有兩種模式:表共享讀鎖和表獨佔寫鎖。加讀鎖的命令:lock table 表名 read; 去掉鎖的命令:unlock tables。
支援併發插入:支援查詢和插入操作併發執行(在表尾併發插入)。
鎖排程機制:寫鎖優先。乙個程序請求某個myisam表的讀鎖,同時另乙個程序也請求同一表的寫鎖,mysql如何處理呢?答案是寫程序先獲得鎖。
2、行級鎖:僅對指定的記錄進行加鎖,這樣其他程序還是可以對同乙個表中的其他記錄進行操作。特點:開銷大,加鎖慢;會出現死鎖;鎖粒度最小,發生鎖衝突的概率最低,併發度也最高。
innodb儲存引擎既支援行級鎖,也支援表級鎖,但預設情況下是採用行級鎖。
3、頁級鎖:一次鎖定相鄰的一組記錄。開銷和加鎖時間介於表鎖和行鎖之間;會出現死鎖;鎖定粒度介於表鎖和行鎖治安,併發度一般。
最常用的處理多使用者併發訪問的方法是加鎖。當乙個使用者鎖定資料庫中的某個物件時,其他使用者就不能再訪問該物件。加鎖對併發訪問的影響體現在鎖的粒度上。比如,(表鎖)放在乙個表上的鎖限制對整個表的併發訪問;(頁鎖)放在資料頁上的鎖限制了對整個資料頁的訪問;(行鎖)放在行上的鎖只限制對該行的併發訪問。
樂觀鎖和悲觀鎖的概念,實現方式和使用場景
鎖有兩種機制:悲觀鎖和樂觀鎖。
悲觀鎖,鎖如其名,它對世界是悲觀的,它認為別人訪問正在改變的資料的概率是很高的,所以從資料開始更改時就將資料鎖住,直到更改完成才釋放。
乙個典型的依賴資料庫的悲觀鎖呼叫:
select * from account where name="erica" for update
這條sql語句鎖定了account表中所有符合檢索條件(name="erica")的記錄。本事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。該語句用來鎖定特定的行(如果where子句,就是滿足where條件的那些行)。當這些行被鎖定後,其他會話可以選擇這些行,但不能更改或刪除這些行,直到該語句的事務被commit語句或rollback語句結束終止。需要注意的是,select ...for update要放到mysql的事務種,即begin和commit中,否則不起作用。
悲觀所可能會造成加鎖的時間很長,並發行不好,特別是長事務,影響系統的整體效能。
悲觀所的實現方式:
悲觀鎖,也是基於資料庫的鎖機制實現。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖、寫鎖等,都是在做操作之前先上鎖。
樂觀鎖,它對世界比較樂觀,認為別人訪問正在改變的資料的概率是很低的,所以直到修改完成準備提交所作的修改到資料庫的時候才會將資料鎖住,當你讀取以及改變該物件時並不加鎖,完成更改後釋放。樂觀鎖不能解決髒讀的問題。
樂觀鎖加鎖的時間要比悲觀鎖短,大大提公升了大併發量下的系統整體效能表現。
樂觀鎖的實現方式:
1、大多是基於資料版本(version)記錄機制實現,需要為每一行資料增加乙個版本標識(也就是每一行資料多乙個欄位version),每次更新資料都要更新對應的版本號+1。
工作原理:讀出資料時,將此版本一同讀出,之後更新時,對此版本號加一。此時,將提交的資料的版本資訊與資料庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料,不得不重新讀取該物件並作出更改。
2、使用時間戳來實現
同樣是在需要樂觀鎖控制的table中增加乙個字段,名稱無所謂,字段型別使用時間戳(timestamp),和上面的version類似,也是在更新提交的時候檢查當前資料庫中資料的時間戳和自己更新前取到的時間戳進行對比,如果一致則ok,否則就是版本衝突。
悲觀鎖與樂觀鎖的適用場景:
如果併發量不大,可以使用悲觀鎖解決併發問題;但如果系統的併發量非常大的話,悲觀所定會帶來非常大的效能問題,所以我們就要選擇樂觀鎖定的方法。現在大部分應用都應該是樂觀鎖的。
資料庫 涉及鎖的問題
加鎖 鎖是一種併發控制技術,鎖是用來在多個使用者同時訪問同乙個資料的時候保護資料的。一 有兩種基本的鎖型別 共享鎖 s 多個事務可封鎖乙個共享頁 任何事務都不能修改該頁 通常是該頁被讀取完畢,s鎖立即被釋放。在執行select語句的時候需要給操作物件 表或者一些記錄 加上共享鎖,但加鎖之前需要檢查是...
mysql鎖的問題
鎖表的問題 innodb鎖表問題 死鎖的形成 向innodb資料表中寫資料死鎖。蒐集資料如下 一 形成死鎖的四個必要條件 1 互斥條件 乙個資源每次只能被乙個程序使用。2 請求與保持條件 乙個程序因請求資源而阻塞時,對已獲得的資源保持不放。3 不剝奪條件 程序已獲得的資源,在末使用完之前,不能強行剝...
mysql鎖問題嗎 mysql 鎖問題處理
錯誤資訊如下 time 140122 16 34 23 user host x thread id 19904440 schema x last errno 1205 killed 0 query time 200.911931 lock time 0.000041 rows sent 0 rows...