前面兩篇博客中簡單的聊了下mysql中的索引,今天聊聊mysql(InnoDB引擎)中的鎖以及事務的實現
MySQL(二) MySql經常使用優化
mysql
講到鎖你們應該都不陌生。像是Java中常見的採用CAS算法實現的樂觀鎖,典型的例子就是原子類,經過CAS自旋實現原子操做的更新,悲觀鎖一般都是Synchronized
和Lock
實現。
# 加上lock in share mode
SELECT description FROM book_book lock in share mode;複製代碼
# 加上for update
SELECT description FROM book_book for update;
複製代碼
行鎖與表鎖區別在於鎖的粒度,在Innodb引擎中既支持行鎖也支持表鎖(MyISAM引擎只支持表鎖),只有經過索引條件檢索數據InnoDB才使用行級鎖,不然,InnoDB將使用表鎖。
這裏有個比較疑惑的地方,爲何表鎖不會出現死鎖?在MyISAM中因爲沒有事務,一條SQL執行完鎖就釋放了,不會循環等待,因此只會出現阻塞而不會發生死鎖。可是在InnoDB中有事務就比較疑惑了,但願有了解的小夥伴指點指點@-@算法
下面舉兩個例子說明上面幾種鎖:
# 事務1
BEGIN;
SELECT description FROM book_book where name = 'JAVA編程思想' lock in share mode;
# 事務2
BEGIN;
UPDATE book_book SET name = 'new book' WHERE name = 'new';
# 查看事務狀態
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
trx_id trx_state trx_started trx_tables_locked trx_rows_locked
39452 LOCK WAIT 2018-09-08 19:01:39 1 1
282907511143936 RUNNING 2018-09-08 18:58:47 1 38
複製代碼
事務1給book表加上了共享鎖,事務2嘗試修改book表發生了阻塞,查看事務狀態能夠知道事務一因爲沒有走索引使用了表鎖。
sql
# 事務1
BEGIN;
SELECT description FROM book_book WHERE id = 2 lock in share mode;
# 事務2
BEGIN;
UPDATE book_book SET name = 'new book' WHERE id = 1;
# 查看事務狀態
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
trx_id trx_state trx_started trx_tables_locked trx_rows_locked
39454 RUNNING 2018-09-08 19:10:44 1 1
282907511143936 RUNNING 2018-09-08 19:10:35 1 1
複製代碼
事務1給book表加上了共享鎖,事務2嘗試修改book表並無發生阻塞。這是因爲事務一和事務二都走了索引,因此使用的是行鎖,並不會發生阻塞。
數據庫
意向鎖的意義在於方便檢測表鎖和行鎖之間的衝突
IX IS X S
IX 兼容 兼容 衝突 衝突
IS 兼容 兼容 衝突 兼容
X 衝突 衝突 衝突 衝突
S 衝突 兼容 衝突 兼容
複製代碼
MVCC使得InnoDB更好的實現事務隔離級別中的REPEATABLE READ
間隙鎖使得InnoDB解決幻讀問題,加上MVCC使得InnoDB的RR隔離級別實現了串行化級別的效果,而且保留了比較好的併發性能。
定義:當咱們用範圍條件檢索數據時請求共享或排他鎖時,InnoDB會給符合條件的已有數據的索引加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫作間隙(GAP),InnoDB也會對這個"間隙"加鎖,這種鎖機制就是間隙鎖。
編程
例如:book表中存在bookId 1-80,90-99的記錄。SELECT * FROM book WHERE bookId < 100 FOR UPDATE。InnoDB不只會對bookId值爲1-80,90-99的記錄加鎖,也會對bookId在81-89之間(這些記錄並不存在)的間隙加鎖。這樣就能避免事務隔離級別可重複讀下的幻讀。bash
有問題的同窗能夠指出相互探討,如需轉載請註明出處。
參考文獻:
https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.htmlhttps://www.cnblogs.com/chenpingzhao/p/5065316.html