MySQL的锁

在并发访问时,MySQL采用锁的机制来控制资源的访问规则。

全局锁

全局锁是对整个数据库实例加锁,会让整个库处于只读状态。

flush table with read lock

全局锁常用在全库逻辑备份的时候。如果在备份的过程中,没有对数据库加锁,那么将导致备份得到的库,不是一个逻辑时间点。

执行 set global readonly=true 也可以对整个库加全局锁。但如果发生异常,并不会自动释放全局锁,导致整个库长时间处于只读状态。

全库加锁,在备份期间,整个库将不能执行更新操作,业务会受到很大的影响。如果在从库上加全局锁进行备份,会导致不能执行从主库同步的binlog,将产生主从同步延迟。

对InnoDB引擎来说,在执行 mysqldump 备份时,使用 –single-transaction 参数,在导出数据之前,将会在可重复读隔离级别下开启一个事务,确保数据的一致性。

表级锁

MySQL的表级锁包括 表锁元数据锁(MDL,meta data lock)

表锁

lock tables ... read/write

如果一个线程对一个表持有读锁,那本线程和其他线程对该表的所有写操作将被阻塞。

如果一个线程对一个表持有写锁,那只有本线程可以对该表进行读写。

元数据锁

元数据锁(MDL,meta data lock)是为了保证变更表结构时的安全性。在访问一个表的时候,会自动加上MDL,保证读写的正确性。

当对一个表进行增删改查时,加MDL读锁。读锁之间是不互斥的,因此多个线程可以对同一个表持有多把读锁,同时增删改查。

当修改表结构时,加MDL写锁。读写锁、写锁之间是互斥的。因此,如果有两个线程对一个表进行结构变更,需要等一个完成后,另一个才能执行。

行锁

在InnoDB中,行锁是在需要的时候加上的,并且在事务提交或回滚后释放。因此如果一个事务中需要锁多个行,应该把最可能影响并发的锁尽量放在后面。