MyISAM鎖 與 INNODB鎖
阿新 • • 發佈:2019-02-18
本文雙引號內容為重要點 ,在markdown中雙引號的內容為紅色
一 MyISAM鎖
表鎖
表鎖:不會出現死鎖,容易發生鎖衝突,併發低 (1) 表鎖的兩種模式: "表共享鎖 (Table Read Lock)" 和 "表獨佔寫鎖 (Table Write Lock)" 注: 共享鎖,不會阻塞其他使用者對同一表的讀請求,但會阻塞對同一表的寫請求; 獨佔寫鎖,則會阻塞其他使用者對同一表的讀和寫請求; 讀操作和寫操作之間,以及寫操作之間是序列的; "當一執行緒獲得對一個表的寫鎖後,只有持有鎖的執行緒可以對錶進行更新操作。其他執行緒的讀、寫操作都會等待,直到鎖被釋放為止。" (2) 如何加鎖:MyISAM在sql查詢時會將涉及到的表加上讀鎖,在執行插入或更新時會加寫鎖。使用者也可以用LOCK TABLE去顯式的加鎖。 示例: LOCK tables orders read local,order_detail read local; 加鎖 SELECT SUM(total) FROM orders; SELECT SUM(subtotal) FROM order_detail; UNLOCK tables; 解鎖 "local"選項作用是滿足MYISAM併發插入條件的情況下,允許其他使用者在表尾插入記錄,若不加"local"選項,則不允許。 注: 顯式的加鎖一般是應用於:需要在一個時間點實現多個表的一致性讀取。不然的話,可能讀第一個表時,其他表由於還沒進行讀操作, 沒有自動加鎖,可能資料會發生改變。並且顯示加鎖後只能訪問加鎖的表,不能訪問其他表。
併發鎖
併發鎖:在一定條件下MYISAM支援查詢與插入併發執行
條件:MYISAM引擎系統變數concurrent_insert
值:
0 不允許併發插入
1 程序在讀取表的時候允許另一個程序在表尾插入記錄, MySQL預設設定
2 無論MYISAM表中有沒有空洞,都允許在表尾插入記錄,也允許併發插入記錄表
空洞:指表中的資料出現斷層
鎖的排程情況
預設情況: MyISAM儲存引擎的讀和寫鎖是互斥,讀操作是序列的。在沒有做任何調整的情況下,寫程序會比讀程序 優先獲得鎖,即使讀程序優先於寫程序請求。 大量的更新操作會造成查詢操作很難獲取到讀鎖,從而導致永遠阻塞情況。 "MySQL認為寫請求一般比讀請求重要" 調整方式: 通過"low-priority-updates" 引數,使MyISAM引擎預設給予讀請求以優先的權利。 通過執行命令SET LOW_PRIORITY_UPDATES=1,使該連線發出的更新請求優先順序降低。 通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優先順序
二 INNODB鎖
行鎖
行鎖:會出現死鎖,發生鎖衝突機率低,併發高 "mysql的行鎖是通過索引載入的,要是對了的sql語句沒有走索引,則會全表掃描,行鎖無法實現,取而代之的是表鎖。" (1) 行鎖的兩種模式: "共享鎖(S)" 和 "排他鎖(X)" 注: 共享鎖(S):當一個事務對某幾行上讀鎖時,允許其他事務對這幾行進行讀操作, 但不允許其進行寫操作,也不允許其他事務給這幾行上排它鎖,但允許上讀鎖。 排它鎖(X):當一個事務對某幾個上寫鎖時,不允許其他事務寫,但允許讀。更不允許其他事務給這幾行上任何鎖。 另外,為了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖,這兩種"意向鎖都是表鎖"。 衍生: 意向共享鎖(IS):事務打算給資料行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。 意向排他鎖(IX):事務打算給資料行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。 示例: select math from zje where math > 60 "lock in share mode"; 共享鎖 select math from zje where math > 60 "for update"; 排他鎖 重點: 1.行鎖必須有索引才能實現,否則會自動鎖全表,那麼就不是行鎖了。 2.兩個事務不能鎖同一個索引。 示例: 事務A先執行: select math from zje where math > 60 for update; 事務B再執行: select math from zje where math < 60 for update; 這樣的話,事務B是會阻塞的。如果事務B把 math索引換成其他索引就不會阻塞。 但注意,換成其他索引鎖住的行不能和math索引鎖住的行有重複。 3.insert ,delete , update在事務中都會自動預設加上排它鎖。
鎖衝突
示例:
事務A將某幾行上鎖後,事務B又對其上鎖,鎖不能共存否則會出現鎖衝突。
(但是共享鎖可以共存,共享鎖和排它鎖不能共存,排它鎖和排他鎖也不可以)
死鎖
示例:
兩個事務,事務A鎖住了1~5行,同時事務B鎖住了6~10行,此時事務A請求鎖住6~10行,就會阻塞直到事務B施放6~10行的鎖,
而隨後事務B又請求鎖住1~5行,事務B也阻塞直到事務A釋放1~5行的鎖。死鎖發生時,會產生Deadlock錯誤。
問題
為什麼表鎖不會產生死鎖?
答:鎖對錶進行操作,將全表鎖住之後自然就不會產生死鎖
樂觀鎖
操作資料庫時(更新操作),想法很樂觀,認為這次的操作不會導致衝突。"(一般都需要自己去實現)"
示例:
下單操作包括3步驟:
1.查詢出商品資訊
select (status,status,"version") from t_goods where id=#{id}
2.根據商品資訊生成訂單
3.修改商品status為2
update t_goods
set status=2,version=version+1
where id=#{id} and "version=#{version}";
注:實現樂觀鎖與例項中的紅色字型相關
悲觀鎖
操作資料時,認為此操作會出現資料衝突,所以在進行每次操作時都要通過獲取鎖才能進行對相同資料的操作,
這點跟java中的synchronized很相似,所以悲觀鎖需要耗費較多的時間。
"共享鎖和排它鎖是悲觀鎖的不同的實現"