根据加锁的范围,mysql里面的锁大致可以分为全局锁,表级锁和行锁三类。
全局锁
全局锁就是对整个数据库实例加锁。mysql提供了一个加全局读锁的方法,命令是Flush tables with read lock(FTWRL)。当需要让整个库处于只读的状态,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表都select出来存成文本。
缺点:如果在主库上备份,那么在备份期间都不能执行更新操作,业务基本上就得停摆;如果在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟。
表级锁
mysql里的表级别的锁有两种:一种是表锁,一种是元数据锁。
表锁
语法是:lock tables ... read/write。和FTWRL类似,可以用unlock tables主动释放锁。lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来操作的对象。
举例说明:如果在某个线程A中执行lock tables t1 read,t2 write;这个语句,其他线程写t1,读写t2的语句都会被阻塞。同时,线程A在执行unlock tables之前,也只能执行读t1,读写t2的操作。就连写t1
都不允许,所以也不能访问其他表。(线程A对表t1加读锁,对表t2加写锁,其他线程只能读t1且不能对t2进行读写;本线程只能读t1,可以对t2读写)
元数据锁(metadata lock)
MDL 不需要显式使用,在访问一个表的时候会被自动加上。MDL 的作用是,保证读写的正确性。
行锁
MySQL 的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如 MyISAM 引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB 是支持行锁的。