什么是锁
锁是计算机协调多个进程或线程并发访问某一资源的机制。锁保证数据并发访问的一致性、有效性;锁冲突也是影响数据库并发访问性能的一个重要因素。锁是Mysql在服务器层和存储引擎层的并发控制。加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否已解除、释放锁等。
共享锁和排他锁:
共享锁(读锁):其他事务可以读,但不能写。
排他锁(写锁) :其他事务不能读取,也不能写。
粒度锁
MyISAM 和 MEMORY 存储引擎采用的是表级锁(table-level locking)
BDB 存储引擎采用的是页面锁(page-level locking),但也支持表级锁
InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。
默认情况下,表锁和行锁都是自动获得的,不需要额外的命令。
不同粒度锁的比较
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
特点:表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用,如Web 应用
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
特点:最大程度的支持并发,同时也带来了最大的锁开销。
在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,这决定了在 InnoDB 中发生死锁是可能的。
行级锁只在存储引擎层实现,而Mysql服务器层没有实现。行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
InnoDB锁模式
InnoDB 实现了以下两种类型的行锁:
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:
意向共享锁(IS):事务打算给数据行加共享锁,事务在给一个数据行加共享锁前必须先取得该表的 IS 锁。
意向排他锁(IX):事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的 IX 锁。
锁模式的兼容情况:
如果一个事务请求的锁模式与当前的锁兼容,InnoDB 就将请求的锁授予该事务; 反之, 如果两者不兼容,该事务就要等待锁释放。