mysql 锁

对于 MyIsam 引擎默认是“表”锁——偏“读”:

读锁会阻塞写,而不会影响读:例如一个表 table 被一个session(进程)加了读锁,则不影响其他的 session 读该表,但是会阻塞其他的session 写锁,所谓阻塞就是说必须要等加锁的 session 释放了该表上的锁,其他的 session 才会执行其写锁的命令,否则,该命令将一直等待下去(阻塞) 。

      另外一点,给表加读锁的 session 既不能写该表,也不能读取其他的表,就好比干一件事,你必须先把它干完,否则别想着干其他事

写锁会把读和写都阻塞:给表加写锁的 session,自己可以读该表,但是阻塞了其他的 session 对该表的读和写,而且该 session 也不能读其他的表,必须先干完这件事


由于 MyIsam 引擎读写锁的调度是“写”优先,所以 MyIsam 不适合做以写表为主的引擎,因为写锁后,其他线程很难做任何操作,大量的对表的更新会使得查询很难得到锁,从而造成永远阻塞

对于 innodb 引擎默认是“行”锁——偏“写”:

当查询条件中的 varchar 类型没有加单引号,而且该查询条件的字段为索引字段,如where name=2000(其中name字段为索引字段),mysql 内部会做一个自动类型的转换,索引失效,这时候的行锁会转换成表锁,这是一件非常可怕的事情

对于 innodb 引擎的“间隙锁”:

比如:update table user set username='hello' where age>20 and age<25;

假如此时在数据库表中,没有 age=22 的这条记录(也就是说没有年龄为22 的员工),那么 where 条件的值就是:21 23 24,在这条更新语句没有提交之前,此时,有另外一条sql 也在更新这张表,且就是插入 age =22 的这条记录,按理说 innodb 引擎是行锁,这两条 sql 所操作的行都是不同的行,所以第二条 sql 的 insert 操作也能添加到数据库中,但实际是该 sql 仍然被第一条没提交的 sql 阻塞,直到第一条 sql 执行 commit 操作,第二条 sql 才执行,这个锁叫做“间隙锁”,这也是间隙所的危害

给表的某一行加“行锁”方法:

select XXX for update;

就是在 select 后面加上 for update,其他线程就不能操作该行,表现为阻塞状态,直到该行执行 commit 命令,其他行才有权执行操作

在表上查看锁状态的方法:show status like 'user%';

mysql 锁

对于行锁的优化建议:

mysql 锁

MyIsam 和 innodb 的区别:

mysql 锁