MySQL全局锁和表锁

  • MySQL为处理并发问题提出数据库锁设计
    • 根据加锁的范围,MySQL里面的锁能够大体分为全局锁、表级锁和行锁三类。
  • 全局锁
    • 就是对整个数据库实例加锁。MySQL提供了一个加全局锁的方法,命令是:
    • Flush tables with read lock (FTWRL)
    • 这个语句让数据库处于只读状态,其余的线程的如下语句会被阻塞:数据更新语句(数据的增删查改)、数据定义语句(包括建表、修改表结构等)和更新事务的提交语句。
  • 全局锁的典型使用场景是,作全库逻辑备份。也就是把数据库的每一个表都select出来存成文本。
    • 让整个数据库只读的弊端
      一、若是在主库上备份,在备份期间不能执行更新,业务基本上就得停摆;
      二、若是在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,致使主从延迟。
    • 如何备份数据库还能不影响数据库的正常功能?
      在可重复读隔离级别下开启一个事务。
      官方自带的逻辑备份工具是mysqldump,使用参数是single-transaction的时候,导数据以前就会启动一个事务,来确保拿到一致性视图。因为MVCC的支持,这个过程当中数据是能够正常更新的。
      single-transaction方法只适用于全部的表使用事务引擎的库。

 

  • 何时须要FTWRL呢?
    • 一致性读是好,可是前提是引擎要支持这个隔离级别。对于MyISAM这种不支持事务引擎的,就须要使用FTWRL

 

 

  • 为何使用FTWRL而不是其它全库只读功能?好比set global readonly = true的方式?
    • 一、有些系统中,readonly的值会被用来作其余逻辑,好比用来判断一个库是主库仍是备库。修改global变量的方式影响面更大。
    • 二、在异常处理机制上有差别。执行FTWRL这个命令的客户端异常断开,那么MySQL会自动释放这个全局锁。而整个库设置为readonly以后,若是客户端发生异常,则数据库就会一直保持readonly状态。

 

 

表级锁,MySQL的表级锁也分为两种:一种是表锁,一种是元数据锁(meta data lock,MDL)mysql

 

 

  • 表锁:
    • 表锁的语法是:lock tables ... read/write。
    • lock tables 语法即能限制其余线程的读写操做,也能限制本线程接下来的读写操做。
    • 没有更细粒度的锁的时候,表锁能够用来处理并发的方式。InnoDB支持行锁,因此就不须要使用表锁了。

 

元数据锁MDL(metadata lock)
  • MDL不须要显示使用,在访问一个表的时候会被自动加上。
  • 在MySQL 5.5版本中引入了MDL,当对一个表作增删查改操做的时候,加MDL读锁;当对表结构变动操做的时候,加MDL写锁。

 

 

  • 读锁之间不互斥

 

 

  • 读写锁之间、写锁之间是互斥的。

 

 

给一个小表加个字段,致使整个库挂了?

 

如图所示,sessionA和sessionB不会互斥,可是sessionC在读锁没有释放的时候请求MDL写锁,就会阻塞,那后面须要写锁的也被阻塞了,若是这个表的查询操做还很是频繁,并且客户端有重试机制,这个库的线程很快就会爆满,这个库就崩掉了。
  • 如何安全的给小表加个字段?
    • 一、解决长事务、事务不提交,就会一直占着MDL锁。MySQL的information_schema库的innodb_trx表中,能够查找到当前执行中的事务。
    • 比较理想的机制是,在alter table语句里面设定等待时间,若是在等待时间内拿到MDL写锁最好,拿不到就放弃。之后重试。
    • MariaDB已经合并AliSQL的这个功能,因此这两个开源分支项目都支持DLL NOWAIT/WAIT n这个语法。
    • ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ... 
  • 四个数据库设计语言:DDL(数据定义语言)、DML(数据操做语言)、DCL(数据控制语言)、TCL(事务控制语言)
  • MVCC
MVCC(Multi-Version Concurrency Control)即多版本并发控制。
MySQL的大多数事务型(如InnoDB,Falcon等)存储引擎实现的都不是简单的行级锁。基于提高并发性能的考虑,他们通常都同时实现了MVCC。当前不只仅是MySQL,其它数据库系统(如Oracle,PostgreSQL)也都实现了MVCC。值得注意的是MVCC并无一个统一的实现标准,因此不一样的数据库,不一样的存储引擎的实现都不尽相同。
  • 小结
    • 若是你发现你的应用程序里有lock tables这样的语句,须要追查一下,比较可能的状况是:
      一、要么是系统再用MyISAM这类不支持事务的引擎,要安排升级换引擎;
      二、引擎升级了,代码尚未升级。把lock tables 和 unlock tables 改为begin 和commit,问题就解决了。
  • 思考
    备份通常都会在备库上进行,在用single-transaction方法作逻辑备份的过程当中,若是主库上的一个小表作了一个DDL,好比给表加了一列,这时候,从备库上会看到什么现象?
相关文章
相关标签/搜索