《MySQL技術內幕:InnoDB存儲引擎》讀書筆記五-鎖、索引及事務

1、鎖mysql

1)鎖是數據庫系統區別於文件系統的一個關鍵特性,數據庫使用鎖是爲了支持對共享資源進行併發訪問,提供數據的完整性和一致性。算法

2)每一種數據庫實現鎖的方式都不一樣。sql

 

共享鎖:容許事務讀一行數據。當一個事務得到行h的共享鎖,那麼另外的事務也能夠當即得到行h的共享鎖,這種狀況叫鎖兼容數據庫

排他鎖:容許事務刪除或更新一行數據。在上面的狀況中,若是有事務想要獲取行h的排他鎖,則必須等待事務釋放行h上的共享鎖。這種狀況叫鎖不兼容服務器

 

爲支持在不一樣粒度上進行加鎖操做,InnoDB存儲引擎還支持一種額外的鎖方式:意向鎖,InnoDB支持兩種意向鎖:架構

意向共享鎖:事務想要獲取表中某幾行的共享鎖併發

意向排他鎖:事務想要獲取表中某幾行的排他鎖ide

 

查看當前事務中鎖的狀況,可以使用如下三張表(MySQL 5.7中已經不提倡使用,這幾種表已經deprecated):性能

l  INFORMATION_SCHEMA.INNODB_TRXspa

l  INFORMATION_SCHEMA.LOCKS

l  INNODB_LOCK_WAITS

 

1、一致性的非鎖定讀操做(重點)

指InnoDB存儲引擎經過行多版本控制的方式來讀取當前執行時間數據庫中行的數據。若是讀取的行正在執行DELETE、UPDATE操做,這時讀取操做不會所以而會等待行上鎖的釋放,相反,InnoDB存儲引擎會去讀取行的一個快照數據

       快照數據實際上是當前行數據以前的歷史版本,可能有多個版本,一個行可能有不止一個快照數據,咱們稱這種技術爲行多版本技術,由此帶來的併發控制,稱爲多版本併發控制(MVCC)。

       在Read Committed的事務隔離級別下,對於快照數據,非一致性讀老是讀取被鎖定行的最新一份快照數據。

       在Repeatable Read的事務隔離級別(InnoDB的默認隔離級別)下,則老是讀取事務開始時的行數據版本。

 

2SELECT…FOR UPDATESELECT…LOCK IN SHARE MODE

InnoDB對SELECT支持兩種鎖定:

SELECT…FOR UPDATE:對讀取的行記錄加一個排他鎖,其餘任何鎖都會被阻塞

SELECT…LOCK IN SHARE MODE:對讀取的行記錄加一個共享鎖。其餘事務能夠向鎖定的記錄加共享鎖,可是對於加排他鎖,則會阻塞。

對於非一致性讀鎖定讀,即便讀取的行已經被使用SELECT…FOR UDPADE,也是能夠進行讀取的。

3、外鍵和鎖

對於一個外鍵,若是沒有顯示地對這個列加索引,InnoDB存儲引擎自動對其加一個索引。

 

對父表的SELECT操做,不是使用一致性非鎖定的方式,由於這樣會發生數據不一致的問題,所以這時使用的是SELECT…LOCK IN SHARE MODE方式。主動對父表加一個S鎖,若是這時父表上已經加了排他鎖,那麼子表上的操做會阻塞。

 

4、鎖的算法(重點)

InnoDB中有三種行鎖的算法:

Record Lock:單個行記錄上的鎖

Gap Lock:間隙鎖,鎖定一個範圍,但不包括記錄自己

Next-Key Lock:Gap Lock+Record Lock,鎖定一個範圍,而且鎖定記錄自己。

 

實驗:演示Next-Key Lock算法:

1)創建表:

2)插入數據

這裏插入了6條數據。

3)打開兩個會話:A(左)和B

可看到會話B阻塞住了,由於這是使用的Next-Key Lock算法下,鎖定的是(-無窮, 8)數值區間的全部數值。可是插入9是能夠的,由於9不在這個範圍,對於單值得索引查詢,不須要Gap Lock,只須要加一個Record Lock便可。

注意:InnoDB在REPEATABLE READ模式下,Next-Key Lock是默認的行記錄鎖定算法

5、鎖問題

1)丟失更新:多用戶計算機系統中,各個用戶將遠程數據庫服務器中的同一行數據讀到本地內存中,當各個用戶在本地更新並提交數據庫後,可能會出現有些用戶的更新操做丟失的狀況

解決辦法:須要將事務變成串行操做,而不是併發操做.

2)髒讀:首先有兩個概念:髒頁指在緩衝池中已經修改的頁,但尚未刷新到磁盤,即數據庫實例內存中的頁和磁盤的頁中的數據是不一致的。而髒數據是指緩衝池中被修改的數據,而且尚未提交。

       髒讀指的是在不一樣事務下,能夠讀到另外事務未提交的數據,便可讀到髒數據。

解決辦法:發生髒讀的條件是事務的隔離級別爲READ UNCOMMITTED。

3)不可重複讀:指一個事務內屢次讀同一個數據,在這個事務尚未結束前,另外事務也訪問該同一數據。那麼在第一個事務的兩次讀數據之間,因爲第二個事務的更改,第一個事務兩次讀到的數據可能不同。

不可重讀讀和髒讀的區別是:髒讀是讀到未提交的數據,而不可重複讀讀到的確實是已提交的數據,但違反了數據庫事務的一致性要求。不可重複讀又稱爲幻象問題,InnoDB存儲引擎使用Next-Key Lock避免不可重複讀問題。

六、阻塞

一個事務中的鎖須要等待另外一個事務中的鎖釋放它的資源

2、索引、事務

索引

一個較爲容易誤解的問題是:B+樹索引能找到的只是被查找數據行所在的頁,而後數據庫經過把頁讀入內存,再在內存中進行查找,最後獲得查找的數據。查找方式通常爲二分查找。

索引的使用:

一、對高選擇性字段並從表中取出不多一部分行時,對這個字段添加B+樹索引是很是必要的;

二、對於聯合索引,對聯合字段的查找,然而此時若對非第一列進行查找,效率較低,由於B+樹中以聯合字段的形式進行排序;能夠對第二字段進行排序,這樣可避免再一次的排序。

事務:

InnoDB存儲引擎的事務徹底符合ACID(原子性、一致性、隔離性、持久性)

日誌的實現主要靠redo(重作)、undo記錄

一、事務控制語句:

Ø  START TRANSACTION | BEGIN

Ø  COMMIT

Ø  ROLLBACK

Ø  SAVEPOINT identifier

Ø  RELEASE SAVEPOINT identifier

Ø  ROLLBACK TO [SAVEPOINT] identifier

Ø  SET TRACSACTION

 

二、隱式提交的SQL語句

Ø  DDL語句

Ø  用來隱式地修改mysql架構的操做

Ø  管理語句

 

三、事務隔離級別

Ø  READ UNCOMMITEED:讀不可提交,在另外一個事務沒有提交的狀況下,也能讀取,可能會出現髒讀狀況

Ø  READ COMMITTED:不可重複讀,在事務還未提交的狀況下,另外一事務改變一個數據並提交後,本事務在未提交的狀況下能讀取變動後的數據。這種狀況就是幻讀。因此該種隔離級別會出現幻讀現象。

Ø  REPEATABLE READ:可重複讀,可避免髒讀以及幻讀現象,在本事務未提交的狀況下不會讀到不一樣的數據。

Ø  SERIALIZATION:序列化,沒有併發,雖能避免髒讀、幻讀等狀況,但性能較低

四、很差的事務習慣

1)在循環中提交;

2)使用自動提交;

3)使用自動回滾。

相關文章
相關標籤/搜索