日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql事务基础+基于innodb的行锁+间隙锁+如何锁定行

發布時間:2023/12/3 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql事务基础+基于innodb的行锁+间隙锁+如何锁定行 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README outlines are as follows :

  • 行鎖;
  • 事務;
  • 隔離級別;
  • 行鎖變表鎖;
  • 間隙鎖;
  • 如何鎖定一行;
  • 行鎖總結;
  • 【1】行鎖+事務+存儲引擎基礎

    1、行鎖: 偏向于 innodb 存儲引擎,開銷大,加鎖慢,會出現死鎖; 鎖定粒度最小,發送鎖沖突的概率最低, 并發度最高;
    2、innodb 與 myisam 的兩點區別:

    • 區別1:innodb 支持事務;?
    • 區別2: innodb 采用了 行級鎖;

    補充0、事務定義:?

    • 事務就是一組原子性的sql查詢,或者說一個獨立的工作單元。即事務內的sql語句,要么全部執行成功,要么全部執行失敗;

    補充1:事務及其acid屬性;事務的ACID概念:原子性automicity,一致性consistency,隔離性isolation,持久性durability;

    • 原子性:一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要么全部提交成功,要么全部失敗回滾;
    • 一致性;數據庫總是從一個一致性狀態轉移到另一個一致性狀態;
    • 隔離性:通常來說,一個事務所做的修改在最終提交前,對其他事務都是不可見的;
    • 持久性:一旦事務提交,則其所做的修改就會永久保存到數據庫中;此時即使數據庫崩潰,數據也不會丟失;

    補充2:并發事務帶來的問題:

    • 更新丟失, lost update; 最后的事務更新覆蓋了其他事務所做的更新;
    • 臟讀, dirty read;事務A讀取到了事務B已修改但尚未提交的數據;?
    • 不可重復讀, non-repeatable read;事務A讀取到了事務B已經提交的數據,不符合隔離性;
    • 幻讀, phantom read;事務A讀取到了事務B提交的新增數據;

    幻讀和臟讀的區別:

    • 臟讀是事務A讀取到了事務B里面修改了數據;
    • 幻讀是事務A讀取到了事務B里面新增了數據;

    補充3:事務隔離級別;?臟讀,不可重復讀,幻讀,其實都是數據一致性問題,必須由數據庫提供一定的事務隔離機制來了解決;

    mysql的4種隔離級別

    • 級別1)READ UNCOMMITED 未提交讀:事務的修改,即使沒有提交,對其他事務也是可見的;
    • 級別2)READ COMMITTED 提交讀:一個事務從開始直到提交之前,所做的任何修改對其他事務不可見的;
    • 也叫不可重復讀,因為兩次執行相同的查詢,可能得到不同的查詢結果;
    • 級別3)REPEATABLE READ 可重復讀:RR 解決了臟讀問題。該級別保證在同一事務中多次讀取同樣記錄的結果是一致的 ;(mysql的默認事務隔離級別)?但 RR 無法解決幻讀問題,幻讀指的是當某個事物在讀取某個范圍內的記錄時,另外一個事務又在該范圍內插入了一條新的記錄,當之前的事務再次讀取到該范圍的記錄時,會產生幻行;?不過 mysql中的 innodb 和 XtraDB 存儲引擎通過多版本并發控制 MVVC(multiversion concurrency control) 解決了幻讀問題;
    • 級別4)SERIALIZABLE 可串行化:最高隔離級別。通過強制事務串行執行,避免了前面說的幻讀問題。簡單說,SERIALIZABLE 會在讀取的每一行數據上都加鎖,所以可能導致大量的超時和鎖征用的問題;實際應用中很少考慮這種隔離級別;

    補充說明:數據庫的事務隔離級別越嚴格,并發副作用越小,但付出的代價也越大。因為事務隔離級別實質上就是使事務在一定程度上串行化進行,這顯然與并發是矛盾的。 同時,不同的應用對讀一致性和事務隔離程度的要求也是不同的。如許多應用對不可重復讀和幻讀不care, 但關心數據并發訪問的能力;

    查看當前數據庫的事務隔離級別: ?show variables like 'tx_isolation' ;

    =======================================================================================

    【2】行鎖荔枝

    2.0)造數

    -- 造數據: use mybatis; -- 行鎖荔枝 drop table if exists test_innodb_lock_tbl; create table test_innodb_lock_tbl (`rcrd_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '記錄編號',`a` int NOT NULL default 0 COMMENT '列a',`b` varchar(20) NOT NULL default '' COMMENT '列b',PRIMARY KEY (`rcrd_id`) ) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8 COMMENT='innodb行鎖測試表';-- 插入數據 -- 新建存儲過程-調用函數批量插入數據 drop procedure if exists insert_test_innodb_lock_tbl; delimiter ## create procedure insert_test_innodb_lock_tbl(in start_num int, in max_num int) begin declare i int default 0;set autocommit=0;repeat set i=i+1;INSERT INTO mybatis.test_innodb_lock_tbl (a, b)VALUES(rand_num(), rand_str(10));until i = max_numend repeat;commit; end ## delimiter ;call insert_test_innodb_lock_tbl(0, 10) ;-- 建立索引 alter table test_innodb_lock_tbl add key `idx_a` (`a`) comment '索引a' ; alter table test_innodb_lock_tbl add key `idx_b` (`b`) comment '索引b' ; -- 查看索引 show index from test_innodb_lock_tbl; -- 查詢數據 select * from test_innodb_lock_tbl;

    2.1)行鎖基本演示:

    補充: 一旦會話1更新數據后且提交事務后, 會話2等待鎖釋放的線程結束阻塞狀態,立即執行更新操作并更新成功;?

    2.2)會話1操作具體步驟:

    2.3)會話2操作具體步驟:

    ============================================================================

    【補充荔枝】 會話1和會話2 各自更新不同的行,則兩個會話間沒有任何影響; 不存在說 會話1在沒有提交事務前阻塞會話2的情況;?

    【注意】索引失效行鎖變表鎖, 當索引使用不當時, 行鎖會升級為表鎖;
    當varchar 類型 作為where子句的查詢條件時, 如果沒有寫單引號,則行鎖升級為表鎖;
    但是在mysql8中,如果沒有寫單引號,則sql 執行報錯。

    ============================================================================

    【3】間隙鎖

    1)什么是間隙鎖??
    當我們用范圍條件而不是相等條件檢索數據,并請求共享或排他鎖時, innodb 會給符合條件的已有數據記錄的索引項加鎖, 對于鍵值在條件范圍內但并不存在的記錄,叫做間隙-GAP
    innodb 也會對這個間隙加鎖,這種鎖機制就是所謂的間隙鎖;(next-key鎖);

    會話1:

    會話2:

    2)間隙鎖的危害:?

    • 危害1)因為query執行過程中通過范圍查找的話, 它會鎖定整個范圍內所有的索引鍵值,即使這個鍵值不存在;?
    • 危害2)間隙鎖有一個比較致命的弱點,就是當鎖定一個范圍鍵值后,即使某些不存在的鍵值也會被無辜的鎖定, 而造成在鎖定的時候無法插入鎖定鍵值范圍內的任何數據。在某些場景下這可能會對性能造成很大危害; ??

    ============================================================================

    【4】如何鎖定一行?

    0)執行如下語句,就可以鎖定行(在查詢語句最后加上 for update 即可);?
    select * from test_innodb_lock_tbl where a=101 for update;

    1)會話1:

    mysql> select * from test_innodb_lock_tbl order by a; +---------+-----+------------+ | rcrd_id | a ? | b ? ? ? ? ?| +---------+-----+------------+ | ? ? 107 | 101 | pkdOHXNXzD | | ? ? 111 | 102 | 2000 ? ? ? | | ? ? 103 | 103 | 181125 ? ? | | ? ? 108 | 104 | 181125 ? ? | | ? ? 106 | 105 | 181125 ? ? | | ? ? 109 | 106 | IsNODBWgNx | | ? ? 105 | 107 | xaMIfDzMnd | | ? ? 102 | 108 | zhou222 ? ?| | ? ? 104 | 109 | tZPdVseqrN | | ? ? 110 | 109 | vkNjJSlDhd | +---------+-----+------------+ 10 rows in set (0.00 sec)mysql> mysql> mysql> begin; Query OK, 0 rows affected (0.00 sec)mysql> select * from test_innodb_lock where a=8 fro update; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'fro update' at line 1 mysql> mysql> select * from test_innodb_lock where a=101 for update; ERROR 1146 (42S02): Table 'mybatis.test_innodb_lock' doesn't exist mysql> mysql> select * from test_innodb_lock_tbl where a=101 for update; +---------+-----+------------+ | rcrd_id | a ? | b ? ? ? ? ?| +---------+-----+------------+? | ? ? 107 | 101 | pkdOHXNXzD | +---------+-----+------------+ 1 row in set (0.00 sec)mysql> commit; Query OK, 0 rows affected (0.00 sec)

    2)會話2:

    mysql> update test_innodb_lock_tbl set b='xxx' where a=101; Query OK, 1 row affected (22.25 sec) Rows matched: 1 ?Changed: 1 ?Warnings: 0

    ============================================================================

    ?

    【5】行鎖總結

    1)innodb存儲引擎:由于實現了行級鎖定,雖然在鎖機制的實現方面所帶來的性能損耗高于表級鎖, 但整體上的并發處理能力要遠遠高于 myisam的表級鎖定;當系統并發量較高時,innodb的整體性能和myisam相比就會有比較明顯的優勢了;
    2)但是, innodb的行級鎖同樣也有其脆弱的一面,當我們使用不當的時候,可能會讓 innodb的整體性能表現不僅不能比 myisam高,甚至會更差;

    3)如何分析行鎖定?
    3.1)通過檢查 innodb_row_lock 狀態變量來分析系統上的行鎖的爭奪情況;
    show status like 'innodb_row_lock%';?

    狀態說明如下:

    • Innodb_row_lock_current_waits:當前正在等待鎖定的數量;
    • Innodb_row_lock_time:從系統啟動到現在鎖定總時間長度;(等待總時長-比較重要)
    • Innodb_row_lock_time_avg:每次等待鎖花費的平均時間; (等待時長均值-比較重要)
    • Innodb_row_lock_time_max:從系統啟動到現在等待最長的一次所花費的時間;
    • Innodb_row_lock_waits:系統啟動后到現在總共等待的次數;(等待總次數-比較重要)

    【注意】 等待次數很高,其每次等待時長不小的時候,我們就需要分析系統中為什么會有如此多的等待;然后根據分析結果著手指定優化計劃(show profile);

    4)優化建議:

    • 建議1)盡可能讓所有數據檢索都通過索引來完成,避免無索引行鎖升級為表鎖;(如varchar類型在where子句中不加單引號‘’)
    • 建議2)合理設計索引,盡量縮小鎖的范圍;
    • 建議3)盡可能少的檢索條件,避免間隙鎖;
    • 建議4)盡量控制事務大小,減少鎖定資源量和時間長度;
    • 建議5)盡可能低級別事務隔離;

    ?

    總結

    以上是生活随笔為你收集整理的mysql事务基础+基于innodb的行锁+间隙锁+如何锁定行的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。