基于锁的属性分类:共享锁(读锁)、排他锁(写锁)。
基于锁的粒度分类:行级锁((innodb )、表级锁( innodb、myisam)、页级锁( innodb引擎)、记录锁、间隙锁、临键锁。
按属性分:
共享锁(share lock):共享锁又称读锁,简称S锁;当一个事务为数据加上读锁之后,其他事务只能对该数据加读锁,而不能对数据加写锁,直到所有的读锁释放之后其他事务才能对其进行加持写锁。共享锁的特性主要是为了支持并发的读取数据,读取数据的时候不支持修改,避免出现重复读的问题。
排他锁(exclusive lock)︰排他锁又称写锁,简称×锁;当一个事务为数据加上写锁时,其他请求将不能再为数据加任何锁,直到该锁释放之后,其他事务才能对数据进行加锁。排他锁的目的是在数据修改时候,不允许其他人同时修改,也不允许其他人读取,避免了出现脏数据和脏读的问题。
————————————————
一、表锁
表读锁 lock table read; 一个session设置读锁,当前session更新和插入都会报错,另一个session只能读,写会阻塞。
表写锁 lock table write; 一个session设置写锁,当前session可以增删改查都可以,另一个session不能读写都会阻塞,直到锁被释放。 unlock tables;
二、共享锁
行共享锁: select * from 表名 where id = 1 lock in share mode; 当一个session设置共享锁,另一个session也可以设置共享锁成功。查询操作不影响,当第一个session进行更新操作会阻塞,第二个session进行更新操作时会因为发生死锁而退出,此时第一个session设置成功。第一个session可以读写,第二个session也可以读,但是写操作直到第一个session commit之后才能进行操作。
三、排他锁
行排他锁 select * from 表名 where id = 1 for update; 当一个session设置排他锁,另一个session在设置锁时会阻塞,第一个session可以读写,第二个session也可以读,但是写操作直到第一个session commit之后才能进行操作。
注:1、mysql 会把 update insert delete 操作 隐式添加for update;
2、mysql 加行锁时,如果改sql没有用到索引,那它会将转换成表锁。行锁并不是争对记录,而是对索引。
mysql 记录锁 间隙锁 临键锁
————————————————
行级锁是针对索引进行加锁
如果加锁时候没有命中索引的话,则会转变为对每一行数据都加上行级锁,而不是加表锁
可以通过一个查询所有事务的锁状态的语句来验证
在8.0中运行以下语句
SELECT * FROM performance_schema.data_locks
结果是大量的行锁和一个意向锁和一些间隙锁supremum pseudo-record,OK,问题结束,没有索引时加行锁会转变成给每一行都加行锁。(其实用快照读也能测出来和lock tables的不一致)
————————————————