表鎖
打開兩個session連接數據庫:
先建表插入數據:
create table mylock(
id int not null primary key auto_increment,
name varchar(20)
)engine=myisam;
insert into mylock(name) values('a');
insert into mylock(name) values('b');
insert into mylock(name) values('c');
insert into mylock(name) values('d');
insert into mylock(name) values('e');
這裏的引擎是myisam。因爲表鎖主要偏向myisam。一鎖就鎖整張表。
讀鎖
給mylock
加上讀鎖(session1)。
此時兩個對數據庫的session都能夠完成“讀”。
(之後我們稱執行lock table mylock read
的session爲session1,就是一個cmd窗口;另一個cmd窗口稱爲session2)。
現在session1嘗試update。
始作俑者改不了。
但是:
session2update
的時候阻塞了。
之後當session1解鎖之後:
session2纔會更新成功:
這就是鎖表的壞處。人家要改數據,還得等着你先把表給解鎖了。
同樣的,insert
也會阻塞:
寫鎖
session1給mylock
表加上寫鎖:
看看session1的讀寫情況:
能讀能改。
打開session2:
連讀都阻塞住了。
這是萬萬不可的,如果連讀都不能讀,那就什麼操作都無法進行。
這裏我們就可以理解爲什麼寫鎖
被稱作獨佔鎖
。
同時,我們也能理解myisam
爲什麼被稱作偏讀
的引擎。
行鎖
建表:
我給兩個字段都加上了索引。
插入一些數據:
現在我開兩個session,希望同時對id=5的這一行進行update。
session1:
修改成功。
session2:
阻塞住了。
session1commit
:
session2解除了阻塞並查看:
可以看到他等了4秒多。
session2commit
並查看:
可以看到,mysql確實保證了可重複讀。
而且,innodb默認的行鎖保證了併發操作同一條數據時的先後性。
再開第三個session,它作爲旁人來看:
它看到的是最終修改後的結果(5002),這是合理的。
如果兩個人操作不同的數據,那是互不影響的:
另一方面,如果索引失效,則會直接卡死:
我的value是varchar型的,並且建了索引。我使用了7000這個數值,會使索引失效。這將導致阻塞。