偏向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...