深入理解Mysql 鎖 事務與併發控制

2021-08-21 04:48:07 字數 3464 閱讀 5152

下面大部分博文**

sql 語句主要可以劃分為以下 3 個類別。

ddl(data definition languages)語句:資料定義語言,這些語句定義了不同的資料段、資料庫、表、列、索引等資料庫物件的定義。常用的語句關鍵字主要包括 create、drop、alter等。

dml(data manipulation language)語句:資料操縱語句,用於新增、刪除、更新和查詢資料庫記錄,並檢查資料完整性,常用的語句關鍵字主要包括 insert、delete、udpate 和select 等。(增添改查)

dcl(data control language)語句:資料控制語句,用於控制不同資料段直接的許可和訪問級別的語句。這些語句定義了資料庫、表、字段、使用者的訪問許可權和安全級別。主要的語句關鍵字包括 grant、revoke 等。

ddl 語句:

ddl 是資料定義語言的縮寫,簡單來說,就是對資料庫內部的物件進行建立、刪除、修改的操作語言。它和 dml 語言的最大區別是 dml 只是對錶內部資料的操作,而不涉及到表的定義、結構的修改,更不會涉及到其他物件。ddl 語句更多的被資料庫管理員(dba)所使用,一般的開發人員很少使用。

共享鎖也稱為讀鎖,讀鎖允許多個連線可以同一時刻併發的讀取同一資源,互不干擾;

排他鎖也稱為寫鎖,乙個寫鎖會阻塞其他的寫鎖或讀鎖,保證同一時刻只有乙個連線可以寫入資料,同時防止其他使用者對這個資料的讀寫。

鎖的開銷是較為昂貴的,鎖策略其實就是保證了執行緒安全的同時獲取最大的效能之間的平衡策略。

表鎖是mysql最基本的鎖策略,也是開銷最小的鎖,它會鎖定整個表;

具體情況是:若乙個使用者正在執行寫操作,會獲取排他的「寫鎖」,這可能會鎖定整個表,阻塞其他使用者的讀、寫操作;

若乙個使用者正在執行讀操作,會先獲取共享鎖「讀鎖」,這個鎖執行其他讀鎖併發的對這個表進行讀取,互不干擾。只要沒有寫鎖的進入,讀鎖可以是併發讀取統一資源的。

通常發生在ddl語句\dml不走索引的語句中,比如這個dml update table set columna=」a」 where columnb=「b」. 

如果columnb欄位不存在索引(或者不是組合索引字首),會鎖住所有記錄也就是鎖表。如果語句的執行能夠執行乙個columnb欄位的索引,那麼會鎖住滿足where的行(行鎖)。

通過select * from information_schema.innodb_trx這一句可以看每個事務的鎖的情況

我在事務a中查詢一條資料

select * from tab1 where column1 = *** for update   column1是沒有索引的

這時trx_rows_locked鎖的是全表的數量,當我給column1加上索引時,就只鎖了一行

行鎖可以最大限度的支援併發處理,當然也帶來了最大開銷,顧名思義,行鎖的粒度實在每一條行資料。

乙個事務中多次執行統一讀sql,返回結果一樣。 

這個隔離級別解決了髒讀的問題,幻讀問題(現在網路上還有很多文章說,repetable read級別會有幻讀問題,其實已經沒有了)。這裡指的是innodb的rr級別,innodb中使用next-key鎖對」當前讀」進行加鎖,鎖住行以及可能產生幻讀的插入位置,阻止新的資料插入產生幻行。 

mvcc(multiple-version-concurrency-control)是個行級鎖的變種,它在普通讀情況下避免了加鎖操作,因此開銷更低。 

雖然實現不同,但通常都是實現非阻塞讀,對於寫操作只鎖定必要的行

注意:select …… from where…… (沒有額外加鎖字尾)使用mvcc,保證了讀快照(mysql稱為consistent read),所謂一致性讀或者讀快照就是讀取當前事務開始之前的資料快照,在這個事務開始之後的更新不會被讀到。詳細情況下文select的詳述。

對於加鎖讀select with for update(排他鎖) or lock in share mode(共享鎖)、update、delete語句,要考慮是否是唯一索引的等值查詢。

mvcc 可以保證,假如說你這條資料被很多地方用到,然後我這個地方加了鎖,不會影響其它沒加鎖的地方,比如說我加了for update,如果沒有mvcc,則所有查詢都會被阻塞,有了mvcc,就只有同樣加for update會被阻塞

對於使用到唯一索引 等值查詢:比如,where columna=」…」 ,如果columna上的索引被使用到,

那麼會在滿足where的記錄上加行鎖(for update是排他鎖,lock in shared 是共享鎖,其他寫操作加排他鎖)。這裡是行級鎖,record lock。

我拿id作了驗證,只鎖住了相關行

對於範圍查詢(使用非唯一的索引):

比如(做範圍查詢):where columna between 10 and 30 ,會導致其他會話中10以後的資料都無法插入(next key lock),從而解決了幻讀問題。

事務1相關行是25行

我們用select * from information_schema.innodb_trx查詢一下鎖住的行

發現它鎖了51行,也就是說它不僅鎖了相關的25行,還鎖住了周圍的行.

將事務1的sql改一下

select * from t_product where sort_id between 182 and 183 for update;

再次執行事務1(未提交)

然後寫一新的事務2

set autocommit = 0;

start transaction;

select * from t_product where sort_id=181 for update;

可以發現,這個查詢並沒有被阻塞,也就是說181的資料都沒有被鎖,改一下sql

select * from t_product where sort_id=184 for update;

就發現184的資料已經被鎖了

上面的實驗就是證明此文對於範圍查詢,鎖會怎麼鎖的說法是對的

這裡是next key lock 會包括涉及到的所有行。

next key lock=recordlock+gaplock,不僅鎖住相關資料,而且鎖住邊界,從而徹底避免幻讀

二 深入理解MySql鎖與事務隔離級別

mvcc主要是為了提高高併發的讀寫效能,不用加鎖就能讓多個事務併發讀寫 對於事務id為12的操作,先查詢select from account 建立了查詢快照,記錄執行sql這一刻最大的已提交事務id 快照點已提交最大事務id 對於事務13的操作,先刪除id 1的記錄,然後更新id 2的記錄,再提交...

mysql 索引深入理解 深入理解MySql的索引

為什麼索引能提高查詢速度 先從 mysql的基本儲存結構說起 mysql的基本儲存結構是頁 記錄都存在頁裡邊 各個資料頁可以組成乙個雙向鍊錶每個資料頁中的記錄又可以組成乙個單向鍊錶 每個資料頁都會為儲存在它裡邊兒的記錄生成乙個頁目錄,在通過主鍵查詢某條記錄的時候可以在頁目錄中使用二分法快速定位到對應...

深入理解MyBatis MyBatis事務

mybatis可以通過xml配置檔案設定是否進行事務管理,事務管理主要包括事務的提交,回滾等 本文主要介紹了事務的入口,mybatis事務操作對資料庫select操作和update操作的影響等 個人主頁 tuzhenyu s page string resource mybatis config.x...