mysql有很多锁包括:悲观锁、乐观锁、表锁、行锁、临间锁、间隙锁、记录锁、共享锁、排他锁、意向共享锁、意向排他锁。
mysql中的锁的机制大部分都是采用的悲观锁。
行锁与表锁
mysql的行锁是基于索引添加的。
产生的原因:sql使用走了索引,但是仍不提交,就产生了行级别的死锁。
模拟行锁
首先navicat打开两个会话窗口连接A和B,A会话中设置为手动提交,会话B中设置自动提交。
表test_lock有一个name的索引
会话A更新数据
会话B也更新这条数据-fail
会话B更新其他数据-ok
模拟表锁
把表的索引字段都去掉,A会话更新但未提交,B会话更新和删除都不能操作该表
由此可见
行锁:当某个会话更新语句中走了索引,并且该会话并没有提交时,该条记录是被锁住,其他记录仍然可以修改。
表锁:当某个会话更新语句中没有走索引,并且该会话并没有提交时,该表被锁住,任何记录都不可以修改,仍可以查询。
会话A:
-- 设置当前会话是手动提交-关闭自动提交来模拟表锁
show variables like 'autocommit';
set autocommit=off;
show variables like 'autocommit';
set autocommit=on;
select * from test_lock where name='张飞';
会话B:
update test_lock set name='张飞1' where name='张飞';
select … for update 是行锁还是表锁
A会话
show variables like 'autocommit';
set autocommit=off;
select * from test_lock where id=1 for update;
B会话,更新ID=1的数据就会超时,其他数据正常
结论:
当select走了索引for update是行锁
当select没有走索引for update是表锁
如何解决锁表
查看未提交的事务
select * from information_schema.innodb_trx
解锁
kill trx_mysql_thread_id