按照锁的粒度划分:行锁、表锁、页锁
行锁
行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。可能会出现死锁的情况
共享锁用法(Shared Locks 简称S锁 读锁):
若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
#共享锁就是允许多个线程同时获取一个锁,一个锁可以同时被多个线程拥有
select ... lock in share mode;
排它锁用法(Exclusive Locks 简称X 锁 写锁):
若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
#排它锁,也称作独占锁,一个锁在某一时刻只能被一个线程占有,其它线程必须等待锁被释放之后才可能获取到锁。
select ... for update
表锁
表级锁是mysql锁中粒度最大的一种锁,表示当前的操作对整张表加锁,资源开销比行锁少,不会出现死锁的情况,但是发生锁冲突的概率很大。被大部分的mysql引擎支持,MyISAM和InnoDB都支持表级锁,但是InnoDB默认的是行级锁。
共享锁用法:
LOCK TABLE table_name [ AS alias_name ] READ
排它锁用法:
LOCK TABLE table_name [AS alias_name][ LOW_PRIORITY ] WRITE
解锁用法:
unlock tables;
当然MySQL InnoDB存储引擎中还有几种特殊的表锁,如下
- 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
- 自增锁(AUTO-INC Locks):特殊表锁,自增长计数器通过该“锁”来获得子增长计数器最大的计数值。
IS和IX,是InnoDB两种内部使用的意向锁(Intention Locks)这些会开单独的文章进行总结
比较
锁类型 | 性能 | 死锁 | 粒度 | 并发性能 | 支持的引擎 |
---|---|---|---|---|---|
表级锁 | 开销小,加锁快 | 不会出现死锁 | 锁定粒度大 | 发生锁冲突的概率最高,并发度最低 | InnoDB、MyISAM、MEMORY、BDB |
行级锁 | 开销大,加锁慢 | 会出现死锁 | 锁定粒度最小 | 发生锁冲突的概率最低,并发度最低 | InnoDB |
页面锁 | 开销和加锁时间界于表锁和行锁之间 | 会出现死锁 | 锁定粒度界于表锁和行锁之间 | 并发度一般。 | BDB |