資料庫之樂觀鎖,悲觀鎖

2021-09-24 13:43:30 字數 4066 閱讀 7597

樂觀鎖

1.只在提交操作時檢查是否違反資料完整性。使用自增長的整數表示資料版本號。更新時檢查版本號是否一致,比如資料庫中資料版本為6,更新提交時version=6+1,使用該version值(=7)與資料庫version+1(=7)作比較,如果相等,則可以更新,如果不等則有可能其他程式已更新該記錄,所以返回錯誤。

2.使用時間戳來實現.

悲觀鎖

遮蔽一切可能違反資料完整性的操作。在讀資料時,使用的是共享鎖,在寫入是時使用的是排他鎖。
mysql行級鎖、表級鎖、頁級鎖詳細介紹

總結:

表級鎖myasim:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。

行級鎖innodb:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度最高。

頁級鎖bdb:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

myisam強調的是效能 , 更適合於以查詢為主。innerdb 則強調的是安全,且支援事物,更適合於以刪改為主。

innodb實現了兩種型別的行鎖

共享鎖(s):共享鎖就是我讀的時候,你可以讀,但是不能寫。

排他鎖(x):排他鎖就是我寫的時候,你不能讀也不能寫。

delete from table時,innodb不會重新建立表,而是一行一行的刪除。

開始:頁級:引擎 bdb。

表級:引擎 myisam , 理解為鎖住整個表,可以同時讀,寫不行

行級:引擎 innodb , 單獨的一行記錄加鎖

表級,直接鎖定整張表,在你鎖定期間,其它程序無法對該錶進行寫操作。如果你是寫鎖,則其它程序則讀也不允許

行級,,僅對指定的記錄進行加鎖,這樣其它程序還是可以對同乙個表中的其它記錄進行操作。

頁級,表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。

mysql 5.1支援對myisam和memory表進行表級鎖定,對bdb表進行頁級鎖定,對innodb表進行行級鎖定。

對write,mysql使用的表鎖定方法原理如下:

如果在表上沒有鎖,在它上面放乙個寫鎖。

否則,把鎖定請求放在寫鎖定佇列中。

對read,mysql使用的鎖定方法原理如下:

如果在表上沒有寫鎖定,把乙個讀鎖定放在它上面

否則,把鎖請求放在讀鎖定佇列中。

innodb使用行鎖定,bdb使用頁鎖定。對於這兩種儲存引擎,都可能存在死鎖。這是因為,在sql語句處理期間,innodb自動獲得行鎖定和bdb獲得頁鎖定,而不是在事務啟動時獲得。

行級鎖定的優點:

• 當在許多執行緒中訪問不同的行時只存在少量鎖定衝突。

• 回滾時只有少量的更改。

• 可以長時間鎖定單一的行。

行級鎖定的缺點:

• 比頁級或表級鎖定占用更多的記憶體。

• 當在表的大部分中使用時,比頁級或表級鎖定速度慢,因為你必須獲取更多的鎖。

• 如果你在大部分資料上經常進行group by操作或者必須經常掃瞄整個表,比其它鎖定明顯慢很多。

• 用高階別鎖定,通過支援不同的型別鎖定,你也可以很容易地調節應用程式,因為其鎖成本小於行級鎖定。

在以下情況下,表鎖定優先於頁級或行級鎖定:

• 表的大部分語句用於讀取。

• 對嚴格的關鍵字進行讀取和更新,你可以更新或刪除可以用單一的讀取的關鍵字來提取的一行:

• update tbl_name set column=value where unique_key_col=key_value;

• delete from tbl_name where unique_key_col=key_value;

• select 結合並行的insert語句,並且只有很少的update或delete語句。

• 在整個表上有許多掃瞄或group by操作,沒有任何寫操作。

/* ************************* mysql 鎖表型別和解鎖語句 ************************* */

如果想要在乙個表上做大量的 insert 和 select 操作,但是並行的插入卻不可能時,可以將記錄插入到臨時表中,然後定期將臨時表中的資料更新到實際的表裡。可以用以下命令實現:

複製****如下:

bulk_insert_buffer_size

批量插入快取大小, 這個引數是針對myisam儲存引擎來說的.適用於在一次性插入100-1000+條記錄時, 提高效率.預設值是8m.可以針對資料量的大小,翻倍增加.

concurrent_insert

併發插入, 當表沒有空洞(刪除過記錄), 在某程序獲取讀鎖的情況下,其他程序可以在表尾部進行插入.

值可以設0不允許併發插入, 1當表沒有空洞時, 執行併發插入, 2不管是否有空洞都執行併發插入.

預設是1 針對表的刪除頻率來設定.

delay_key_write

針對myisam儲存引擎,延遲更新索引.意思是說,update記錄時,先將資料up到磁碟,但不up索引,將索引存在記憶體裡,當表關閉時,將記憶體索引,寫到磁碟. 值為 0不開啟, 1開啟. 預設開啟.

delayed_insert_limit, delayed_insert_timeout, delayed_queue_size

延遲插入, 將資料先交給記憶體佇列, 然後慢慢地插入.但是這些配置,不是所有的儲存引擎都支援, 目前來看, 常用的innodb不支援, myisam支援. 根據實際情況調大, 一般預設夠用了

/* ******************** mysql innodb 鎖表與鎖行 ********************==== */

由於innodb預設是row-level lock,所以只有「明確」的指定主鍵,mysql才會執行row lock (只鎖住被選取的資料例) ,否則mysql將會執行table lock (將整個資料表單給鎖住)。

舉個例子: 假設有個表單products ,裡面有id跟name二個字段,id是主鍵。

例1: (明確指定主鍵,並且有此筆資料,row lock)

複製****如下:

select * from products where id=『3』 for update;

select * from products where id=『3』 and type=1 for update;

例2: (明確指定主鍵,若查無此筆資料,無lock)

複製****如下:

select * from products where id=』-1』 for update;

例3: (無主鍵,table lock)

複製****如下:

select * from products where name=『mouse』 for update;

例4: (主鍵不明確,table lock)

複製****如下:

select * from products where id<>『3』 for update;

例5: (主鍵不明確,table lock)

複製****如下:

select * from products where id like 『3』 for update;

注1: for update僅適用於innodb,且必須在交易區塊(begin/commit)中才能生效。

注2: 要測試鎖定的狀況,可以利用mysql的command mode ,開二個視窗來做測試。

在mysql 5.0中測試確實是這樣的

另外:myasim 只支援表級鎖,innerdb支援行級鎖

新增了(行級鎖/表級鎖)鎖的資料不能被其它事務再鎖定,也不被其它事務修改(修改、刪除)

是表級鎖時,不管是否查詢到記錄,都會鎖定表

此外,如果a與b都對錶id進行查詢但查詢不到記錄,則a與b在查詢上不會進行row鎖,但a與b都會獲取排它鎖,此時a再插入一條記錄的話則會因為b已經有鎖而處於等待中,此時b再插入一條同樣的資料則會丟擲deadlock found when trying to get lock; try restarting transaction然後釋放鎖,此時a就獲得了鎖而插入成功

悲觀鎖 面試必備之 樂觀鎖與悲觀鎖

一 什麼是悲觀鎖?什麼是樂觀鎖?1 鎖 lock 在介紹樂觀鎖和悲觀鎖之前,我們先介紹下鎖。在日常生活中,我們經常接觸到鎖這個東西,比如家裡門上的鎖,自行車上的鎖,保險櫃上的鎖等,這些都是為了保障我們的財產安全而上的鎖。而在程式中,鎖是一種保障資料安全的機制和手段。在多併發的情況,當同時多個請求修改...

Mysql鎖機制之 樂觀鎖和悲觀鎖

悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。注 要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性,因為mysql預設使用autocommit模式,也就是說,...

資料庫鎖 樂觀鎖 悲觀鎖理解

參考 mysql innodb中,樂觀鎖 悲觀鎖 共享鎖 排它鎖 行鎖 表鎖 死鎖概念的理解 樂觀鎖最簡單的實現就是在表中加乙個版本號欄位如version,每次新增設定為1,更新的時候檢查版本號是否一致,如果不一致就更新失敗。版本一致才能更新,然後將版本號 1。首先資料庫需要關閉自動提交功能,或者說...