mysql a鎖 MYSQL中的鎖

2021-10-17 19:46:37 字數 2861 閱讀 8536

前言

剛開始接觸mysql,對其鎖機制並不了解,在專案裡面,針對死鎖以及鎖競爭,約定了兩條規則。

對涉及多個業務表的更新,要遵守一定的順序,如按照table-a,table-b,table-c的次序

對乙個業務表的更新,要先排序,按順序執行更新操作。

下面就在mysql中對一些場景進行演示。

死鎖死鎖產生的條件:迴圈等待。我用的客戶端工具是sqlyog,建立兩個連線。以下簡稱session-a, session-b.另,大部分客戶端,都設定成了autocommit,所以需要在每個會話裡,先執行 set autocommit=0。

在測試資料庫裡面,準備兩個表a,b.

資料準備

create table `a` (

`id` int(11) default null,

`name` varchar(50) default null

) engine=innodb default charset=utf8;

create table `b` (

`id` int(11) default null,

`name` varchar(50) default null

) engine=innodb default charset=utf8;

session-a->set autocommit=0;

session-a->insert into a values (1,'data');

session-a->insert into b values (1,'data');

session-a->commit;

好了,現在模擬死鎖場景。

session-a-> update a set name='data from session-a' where id=1;

session-b-> update b set name='data from session-b' where id=1;

session-b-> update a set name='data from session-b' where id=1;

session-a-> update b set name='data from session-a' where id=1;

執行到第三步的時候,session-b就被阻塞住了,

在session-a中執行show full processlist;,顯示當前被阻塞的會話和語句

執行到第四步的時候,控制台輸出update b set name='data from session-a' where id=1;. 同時session-a釋放了所有的鎖並回滾了。同時session-b的阻塞也消失了,完成了a表的更新,執行commit可以順利提交。同時show status like 'innodb_row_lock%';,可以檢視鎖競爭的情況。

上面的例子,是對相同記錄的鎖競爭情況,那麼對於不同的記錄,表現是否相同呢,為了驗證,新加入了兩條記錄

insert into a values (2,'data');

insert into b values (2,'data');

commit;

session-a-> update a set name='data from session-a' where id=2;

session-b-> update b set name='data from session-b' where id=1;

session-b-> update a set name='data from session-b' where id=1;

session-a-> update b set name='data from session-a' where id=2;

最後的結果,完全沒有阻塞。

這個例子,也驗證了innodb加的是行鎖,不同行的更新不會被阻塞。下面詳細講一下mysql的鎖模式。

鎖模式mysql的鎖涉及兩種行鎖s和x,和兩種內部使用的意向鎖is和ix,具體的說明如下:

共享鎖(s):允許乙個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖

排他鎖(x):允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和排他寫鎖

意向共享鎖(is):事務在給乙個資料行加共享鎖前必須先取得該錶的is鎖。

意向排他鎖(ix):事務在給乙個資料行加排他鎖前必須先取得該錶的ix鎖。

我們關心的是那幾個標著相容的單元格。

ix(當前) vs ix(欲加):即表示對不同的行加排他鎖,是ok的。

session-a->select * from a where id=1 for update;

session-b->select * from a where id=2 for update;

ix(當前) vs is:(欲加)和is(當前) vs ix(欲加):即對不同的行加讀鎖和寫鎖,是ok的

session-a->select * from a where id=1 for update;

session-b->select * from a where id=2 lock in share mode;

或者session-a->select * from a where id=1 lock in share mode;

session-b->select * from a where id=2 for update;

其他的,慢慢琢磨。

引用 另有乙個困惑,在原文中提到,innodb的行鎖通過索引來實現,但是我的例子中,兩個表是都沒有建立索引的,希望有人可以解答。

mysql中鎖的概念 mysql中的鎖機制之概念篇

鎖的概念 鎖,在現實生活中是為我們想要隱藏於外界所使用的一種工具。在計算機中,是協調多個程序或執行緒併發訪問某一資源的一種機制。在資料庫當中,除了傳統的計算資源 cpu ram i o等等 的爭用之外,資料也是一種供許多使用者共享訪問的資源。如何保證資料併發訪問的一致性 有效性,是所有資料庫必須解決...

Mysql中的表鎖 行鎖

行鎖 innodb行鎖是通過索引上的索引項來實現的,這一點 ysql與oracle不同,後者是通過在資料中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味者 只有通過索引條件檢索資料,innodb才會使用行級鎖,否則,innodb將使用表鎖。間隙鎖當用範圍條件而不是相等條件檢索資料,並請求...

mysql 鎖的架構 總結Mysql中的鎖

mysql中的鎖 概述myisam支援表鎖,innodb支援表鎖和行鎖,預設為行鎖 表級鎖 開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發量最低 行級鎖 開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的概率小,併發度最高 myisam表級鎖 鎖模式show status li...