Mysql 資料庫表鎖 行鎖

2021-10-18 16:16:33 字數 4263 閱讀 5990

偏向myisam,開銷小,加鎖快,無死鎖,鎖粒度大,發生鎖衝突的概率較高,併發度較低。

測試表,用於表加鎖後的讀寫可能性驗證

create table if not exists table_lock (

id int(10) primary key not null auto_increment comment '自增主鍵',

`name` varchar(24) not null default '' comment '姓名'

手動給表加鎖

lock table table_lock read, book write;
可以看到表已經被占用。

手動解鎖

unlock tables;
測試過程是省略了,就是分別加表的讀寫鎖,在不同mysql連線session中觀察可讀寫性。

myisam引擎的讀寫排程是寫優先,所以myisam不適合作為寫資料場景較多的引擎。當出現較多寫操作的時候,會造成查詢阻塞嚴重

偏向innodb,開銷大,加鎖慢,會出現死鎖,鎖的粒度小,發生鎖衝突的概率低,併發度較高。

innodb與myisam最大的不同是,innodb支援事務,採用了粒度更小的行級鎖。

innodb的預設隔離級別repeatable read(可重讀)

測試表

create table if not exists table_lock2 (

id int(10) primary key not null auto_increment comment '自增主鍵',

`name` varchar(24) not null default '' comment '姓名'

) engine=innodb;

insert into table_lock2 (`name`)

values

('leo'),

('james'),

('irving');

create index table_lock_id_idx on table_lock2(id);

create index table_lock_name_idx on table_lock2(name);

mysql預設是自動提交事務的

show variables like '%autocommit%';
關閉自動提交方便測試

set autocommit = 0;
mysql innodb寫資料預設加鎖

在連線a中修改某條記錄:

update table_lock2 set `name` = 'iversen' where id = 3;
此時並沒有提交事務,在連線a中修改生效

在連線b中查詢,並沒有發生資料變化:

需要連線a執行 commit; 之後,連線b中才能看到資料更新變化

首先在連線a中修改資料:

update table_lock2 set `name` = 'aaa' where id = 1;
之後在連線b中修改資料:

update table_lock2 set `name` = 'bbb' where id = 1;
此時連線a中沒有 commit;,連線b的修改操作將會阻塞,連線a長時間不提交,連線b中操作將會超時。

[sql]update table_lock2 set `name` = 'bbb' where id = 1;

[err] 1205 - lock wait timeout exceeded; try restarting transaction

在連線a commit; 之後,連線b的寫操作將會執行,連線b的操作也需要 commit; 才會生效。

在連線a中修改資料2

在連線b中修改資料1

update table_lock2 set `name` = 'def' where id = 1;
innodb是行鎖,所以寫操作不同行資料,互不影響

在測試表table_lock2建立的時候,分別建立了id和name欄位的索引,此時如果連線a修改某條資料且name欄位varchar型別沒有加上引號,發生隱式的型別轉換,沒有commit的時候,連線b修改另一條資料將會阻塞,此時就是行鎖公升級為了表鎖。

如原有資料為 id = 1,name = 2000

update table_lock2 set id = 4 where `name` = 2000;
原因是因為隱式的型別轉換導致了索引失效。

當使用範圍條件而不是相等條件檢索資料的時候,innodb會給符合條件的已有資料記錄的索引項進行加鎖,對於鍵值在條件範圍內但並不存在記錄即為「間隙」

表table_lock2中沒有id為2的資料時,執行下列sql,innodb仍然會對id這列索引2的位置進行加鎖

update table_lock2 set `name` = 'abc' where id > 1 and id < 6;
此時其他連線插入id = 2的資料時,將會阻塞。

begin;

select * from table_lock2 where id = 2 for update;

-- do something

commit;

如上所示,在commit執行之前,id=2的資料將會被當前連線加鎖,其他連線對該資料的操作將會進入阻塞。

mysql行鎖和表鎖 關於資料庫行鎖與表鎖的認識

mysql mysql innodb儲存引擎 預設是自動提交事務的,所以這個測試,需要先將mysql的autocommit設定為0,關閉自動提交,需要自己手動提交事務 關閉自動提交 set autocommit 0 開啟事務 begin 這裡我主要針對的是悲觀鎖,其實也就是行鎖和表鎖,sql 加上 ...

資料庫行鎖 表鎖 記錄鎖 間隙鎖 臨鍵鎖

行鎖就是一次鎖一行或者多行記錄,mysql的行鎖是基於索引載入的,所以行鎖是要加在索引響應的行上,即命中索引。假設 table的b列為索引字段,則以下更新語句只會鎖b b 的行 update table set a a where b b 行鎖的特徵 鎖衝突概率低,併發性高,但是會有死鎖的情況出現。...

mysql行鎖表鎖區別 mysql表鎖和行鎖區別

一 表鎖 特點 偏向myisam儲存引擎,開銷小,加鎖快 無死鎖 鎖定粒度大,發生鎖衝突的概率最高,併發度最低。我們在編輯表,或者執行修改表的事情了語句的時候,一般都會給表加上表鎖,可以避免一些不同步的事情出現,表鎖分為兩種,一種是讀鎖,一種是寫鎖。我們可以手動給表加上這兩種鎖,語句是 lock t...