行级锁、表级锁、全局锁。
行级锁:
包括行级共享锁(S锁、读锁)、行级排他锁(X锁、写锁)。
锁的都是索引记录,如果没有索引,mysql会使用隐藏列row_id作为聚簇索引。
普通的无条件查询select * from t,是不会加锁的。
带条件的查询语句select * from t where id = 7,假设表中存在索引id=7的这行记录,那么会加行级共享锁;如果表中不存在这行记录,假设表中有数据0,5,10,那么会在(5,10)的范围内加间隙锁(GAP LOCK)。
范围查询语句select * from t where id > 7,假设表中数据有0,5,10,那么会在(5,10]的范围内加临键锁(Next Key Lock),注意临键锁的范围是左开右闭的。
select xxx for update、select xxx lock in share mode会加S锁
update xxx 会加X锁
加了S锁的数据仍然可以被其他事务读取,加了X锁的数据只能被当前事务修改完成才能被其他事务继续访问。
表级锁
常见的是意向锁(读意向锁、写意向锁)、lock table、alter table等。
为啥要有意向锁,假设事务A已经对某行加了行级排他锁,此时事务B想要加表级锁修改数据,如果没有表级别的意向锁,事务B只能逐行判断是否加了行级锁,如果有则需要等待,效率太低。因此引入了意向锁。
事务A加行级锁之前,先在表级别加入写意向锁,表示该表有数据正在被修改,然后再加行级排他锁。事务B检测到表中有写意向锁,则等待A结束释放意向锁再执行操作。
全局锁
影响整个MySQL实例的锁,主要用于全局备份等操作,所有表被锁定为只读状态。