按照锁对数据的操作粒度
行级锁:行级锁是mysql中锁定粒度最细的一种锁。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁
select * from account where id=200 LOCK IN SHARE MODE;
--这是给id=200的这行加一个共享锁
--但注意,如果id并没加索引,那么就会对表进行加锁,而不是行级锁
表级锁:表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。
页级锁:页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。包括临时锁和间隙锁
按照锁的共享策略来分
共享锁:Shared Locks(S锁),针对同一份数据,多个读操作可以同时进行而不会互相影响,但不能进行写操作。
用法 SELECT … LOCK IN SHARE MODE;
排它锁:Exclusive Locks(X锁),当前写操作没有完成前,它会阻断其他写锁和读锁
用法 SELECT … FOR UPDATE;
IS锁:意向共享锁、Intention Shared Lock。当事务准备在某条记录上加S锁时,需要先在表级别加一个IS锁。(意向锁是 InnoDB 自动加的,不需要用户干预。)
IX锁:意向排他锁、Intention Exclusive Lock。当事务准备在某条记录上加X锁时,需要先在表级别加一个IX锁。(意向锁是 InnoDB 自动加的,不需要用户干预。)
自增锁(AUTO-INC锁):自增锁是一种特殊的表级锁,主要用于事务中插入自增字段,也就是我们最常用的自增主键id。通过innodb_autoinc_lock_mode参数可以设置自增主键的生成策略。防止并发插入数据的时候自增id出现异常。
间隙锁:间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
记录锁:记录锁是 封锁记录,记录锁也叫行锁,例如:
SELECT * FROM `test` WHERE `id`=1 FOR UPDATE;
它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。
临键锁:是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。
从策略上分
悲观锁认为对于同一个数据的并发操作,一定是会发生修改的(或者增删改多,查少),哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。
乐观锁则认为对于同一个数据的并发操作,是不会发生修改的(或者增删改少,查多)。在更新数据的时候,会采用不断尝试更新的方式来修改数据。也就是先不管资源有没有被别的线程占用,直接取申请操作,如果没有产生冲突,那就操作成功,如果产生冲突,有其他线程已经在使用了,那么就不断地轮询。乐观的认为,不加锁的并发操作是没有事情的。就是通过记录一个数据历史记录的多个版本,如果修改完之后发现有冲突再将版本返回到没修改的样子,乐观锁就是不加锁。好处就是减少上下文切换,坏处是浪费CPU时间。