Mysql中的锁

前言

大家都知道锁是用来保护并发访问的资源的,Mysql中根据锁的粒度分为了全局锁、表锁以及行锁。今天这篇文章我们一起一起探讨下Mysql中的这三种锁

全局锁

全局锁是Mysql中粒度最粗的锁,它的作用是给数据库实例进行上锁。
一旦该数据库实例被上了全局锁,那么该实例就处于了只读状态,像一些DDL(create/alter table等)语句更新语句(update/insert)就会被阻塞。

你可以使用以下命令给一个数据库实例上全局锁

Flush tables with read lock 

解锁

UNLOCK TABLES 

使用场景

全库逻辑备份

带来的问题

  1. 在主库上备份时:数据无法更新和写入,对业务影响太大
  2. 在从库上备份时:从库无法执行主库同步的binlog,从而导致主从延迟(备份时间越长,延迟越大)

替代方案

一致性视图

mysql中我们获取一致性视图的方法之一:在「可重复读」的隔离级别中开启一个事务。注意这里的前提是你的存储引擎必须支持事务,像MyISAM这种就是不支持事务存储引擎,自然也无法利用一致性视图来代替全局锁来进行全库备份。所以我们的业务场景中一般建议你使用InnoDB存储引擎。

mysql提供了mysqldump备份工具,如果你使用的是InnoDB存储引擎的话。那么你可以使用-single-transaction参数来确保备份的时候使用一致性视图,具体命令如下:

mysqldump -single-transaction -u username -p dbname [tbname ...]> xxx.sql

Mysql中的锁_第1张图片

set global readonly

和全局锁设置全库只读功能类似,mysql提供了set global readonly = true的命令来让全库进入只读状态。但它相比全局锁有以下弊端:

  1. set global readonly 有些场景中会被用来判断是否是主库还是备库。比如当该属性的true时,会认为当前库为备库
  2. 当持有全局锁的客户端发生异常断开时,那么mysql会释放该客户端持有的全局锁,让实例回到正常状态。而set global readonly中的客户端一旦发生异常,实例还是处于readonly状态。在运维人员没发现之前就会导致实例一直处于只读状态

表锁

Mysql中表锁分为两种

  1. Table lock
  2. MDL(Meta data lock 5.5之后引入)

我们今天只探讨Table lock

Table lock的语法是:

lock tables A,B,.... read/write

解锁:

unlock tables

lock table命令会限制当前线程和其他线程对表的操作,具体我们以以下示例来说明:

假设我们线程A中执行以下命令

 lock tables A read, B write; 

Mysql中的锁_第2张图片
如上图所示:
当线程A持有Table A的读锁,Table的写锁时。线程B对TableA的读,对TableB的写就会被阻塞。同时线程A对TableC的读也将会被阻塞。

你可能感兴趣的:(数据库,mysql,后端,数据库)