1 锁等待的例子

session 1: 执行查询但不提交

mysql> begin;

mysql> select * from test where c2 = '1';

session 2: 执行ddl发生等待

mysql> alter table test drop index idx5;

查看show processlist;

| 20487 | mytest | ****:35986 | test123 | Sleep | 3799 | | NULL |
| 20501 | mytest | ****:35990 | test123 | Sleep | 65 | | NULL |
| 20886 | mytest | ****:36076 | test123 | Query | 36 | Waiting for table metadata lock | alter table test drop index idx5 |
| 21463 | mytest | ****:36208 | NULL | Query | 0 | init | show processlist |

ddl发生锁等待"Waiting for table metadata lock"

从information_schema.innodb_trx可以查到未提交的事务

mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 96386
trx_state: RUNNING
trx_started: 2015-01-29 16:34:38
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 20501
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 360
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: READ COMMITTED
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)

show engine innodb status也可看到未提交事务信息。

------------
TRANSACTIONS
------------
Trx id counter 96455
Purge done for trx's n:o < 96339 undo n:o < 0 state: running but idle
History list length 282
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 21463, OS thread handle 0x2b7e50081700, query id 155157 10.189.100.29 mytest init
show engine innodb status
---TRANSACTION 96330, not started
MySQL thread id 20886, OS thread handle 0x2b7e600c2700, query id 153866 10.189.100.30 mytest Waiting for table metadata lock
alter table test drop index idx5
---TRANSACTION 96094, not started
MySQL thread id 20487, OS thread handle 0x2b7e8c081700, query id 146859 10.189.100.29 mytest cleaning up
---TRANSACTION 96386, ACTIVE 744 sec
MySQL thread id 20501, OS thread handle 0x2b7e70081700, query id 153813 10.189.100.30 mytest cleaning up

session 1:执行commit;

commit;

session 2:ddl完成。

2 metadata lock

1)metadata lock是什么

顾名思义,metadata lock即元数据锁。在数据库中元数据即数据字典信息包括db,table,function,procedure,trigger,event等。metadata lock主要为了保证元数据的一致性。而实际上metadata lock不仅仅保护元数据,还可以保证set global read only, flush tables with read lock 操作的顺利执行。

metadata lock也是一种锁。每个metadata lock都会定义锁住的对象,锁的持有时间和锁的类型

锁的作用对象 

metadata lock按锁住的对象来分类,可以分为global, schema, table, function,procedure,trigger,event,commit.这些对象发生锁等待时,我们在show processlist可以分别看到如下等待信息。

Waiting for global read lock
 Waiting for schema metadata lock
 Waiting for table metadata lock
 Waiting for stored function metadata lock
 Waiting for stored procedure metadata lock
 Waiting for trigger metadata lock
 Waiting for event metadata lock
 Waiting for commit lock

锁的持有时间

MySQL从对锁持有的时间上来讲,分为三种:statement,transaction和explicit。

·       Statement:从语句开始执行时获取,到语句执行结束时释放。

·       Transaction:在一个事务中,此事务所涉及到的所有表获取MDL,一直到事务commit或者rollback(或:线程中终清理)才释放。

·       Explicit:需要MDL_context::release_lock()显式释放。语句或者事务结束,也仍然持有。如Lock table, flush .. with lock语句等。

锁的类型

(1)MDL_INTENTION_EXCLUSIVE(IX):意向排他锁,用于global和commit的加锁。

例如:truncate table t1;insert into t1 values(3,'abcde');会加如下锁:

(GLOBAL,MDL_STATEMENT,MDL_INTENTION_EXCLUSIVE)

(SCHEMA,MDL_TRANSACTION,MDL_INTENTION_EXCLUSIVE)

(2)MDL_SHARED(S):只访问元数据,不访问数据。

例如: set golbal_read_only =on;flush tables with read lock;会加如下锁:

(GLOBAL,MDL_EXPLICIT,MDL_SHARED)

(COMMIT,MDL_EXPLICIT,MDL_SHARED)

(3)MDL_SHARED_HIGH_PRIO(SH):用于访问information_scheam表,不涉及数据。

例如: select * from information_schema.tables;show create table xx;desc xxx;会加如下锁:

(TABLE,MDL_TRANSACTION,MDL_SHARED_HIGH_PRIO)

(4)MDL_SHARED_READ(SR): 用于读数据

例如:select * from t1; lock table t1 read;会加如下锁:

(TABLE,MDL_TRANSACTION,MDL_SHARE_READ)

(5)MDL_SHARED_WRITE(SW):用于写数据

例如:insert/update/delete/select .. for update会加如下锁:

(TABLE,MDL_TRANSACTION,MDL_SHARE_WRITE)

select 语句在操作时,需要对表对象持有MDL_SHARED_READ锁。

而DML语句在操作时,需要对表对象持有MDL_SHARED_WRITE锁。但都不需要SCHEMA级别metadata lock锁。

另外drop database 时,需要依次获取以下MDL锁:

1) MDL_INTENSION_EXCLUSIVE(GLOBAL),STATEMENT 级别

2) MDL_EXCLUSIVE(SCHEMA),TRANSACTION级别

3) MDL_EXCLUSIVE (TABLE),TRANSACTION级别。在此database下的每个对象,需要MDL_EXCLUSIVE锁。

(6)MDL_SHARED_UPGRADABLE(SU):是mysql5.6引入的新的Metadata lock,在alter table /create index/drop index会加该锁;可以说是为了online ddl才引入的。特点是允许DML,防止DDL;

(TABLE,MDL_TRANSACTION,MDL_SHARED_UPGRADABLE)

(7)MDL_SHARED_NO_WRITE(SNW):用于防止其他人读写数据,但可以访问元数据。

alter table t1 modify c bigint;(非onlineddl)

(TABLE,MDL_TRANSACTION,MDL_SHARED_NO_WRITE)

(8)MDL_SHARED_NO_READ_WRITE(SNRW):用于防止其他人读写数据,但可以访问元数据。

lock table t1 write;

(TABLE,MDL_TRANSACTION,MDL_SHARED_NO_READ_WRITE)

(9)MDL_EXCLUSIVE(X):防止访问元数据

例如:CREATE/DROP/RENAME TABLE,其他online DDL在rename阶段也持有X锁

(TABLE,MDL_TRANSACTION,MDL_EXCLUSIVE)

最高级别MDL锁,通常用于Drop/Create/Rename等操作。也用于其它对象创建或者删除时,如create trigger等。

锁的兼容性:

other

关于global对象

主要作用是防止DDL和写操作的过程中,执行set golbal_read_only =on或flush tables with read lock;

关于commit对象锁

主要作用是执行flush tables with read lock后,防止已经开始在执行的写事务提交。

insert/update/delete在提交时都会上(COMMIT,MDL_EXPLICIT,MDL_INTENTION_EXCLUSIVE)锁。

关于schema对象锁

主要作用是防止alter/drop/create db与 alter/drop/create table,procedut之间的并发执行

alter/drop/create db会上(SCHEMA,MDL_TRANSACTION,MDL_EXCLUSIVE)

而 alter/drop/create table,procedut会上(SCHEMA,MDL_TRANSACTION,MDL_INTENTION_EXCLUSIVE)

关于table对象锁

主要处理表DDL与DDL, 表DDL与表DML之间的并发

3 其他案例

根据前面介绍的metadata lock加锁规则和锁的兼容性,我们就可以解释出现metadata lock等待的原因了。

1)Waiting for global read lock

我们先够造一个Waiting for global read lock场景:

session1: alter table t1 add c3 bigint; //大表执行需较长时间

session2: set global read only=on; //等待

查看

mysql> show processlist;
+----+------+-----------------+------+---------+------+------------------------------+------------------------------+
| Id | User | Host            | db   | Command | Time | State                        | Info                         |
+----+------+-----------------+------+---------+------+------------------------------+------------------------------+
|  1 | root | localhost:5202  | test | Query   |   12 | altering table               | alter table t1 add c3 bigint |
|  2 | root | localhost:14699 | test | Query   |    3 | Waiting for global read lock | set global read_only=on      |
|  3 | root | localhost:17085 | NULL | Query   |    0 | init                         | show processlist             |
+----+------+-----------------+------+---------+------+------------------------------+------------------------------+
3 rows in set (0.00 sec)

分析

alter table t1 add c3 bigint;会加(GLOBAL,MDL_STATEMENT,MDL_INTENTION_EXCLUSIVE) 语句结束后才释放

set global read only=on;会加(GLOBAL,MDL_EXPLICIT,MDL_SHARED)

由于session1执行时间比较长,一直持有MDL_INTENTION_EXCLUSIVE。从兼容性矩阵可以看出MDL_SHARED和MDL_INTENTION_EXCLUSIVE是不相容的,因此发生“Waiting for global read lock ”等待。直到session 1 alter操作完成释放MDL_INTENTION_EXCLUSIVE。set global read only=on;才可以继续执行。

2)Waiting for commit lock

session1: begin

insert into t1 vlaues(null, 'ab');

session2:flush table with read lock;//成功

session1: commit //发生等待

查看

mysql> show processlist;
+----+------+-----------------+------+---------+------+-------------------------+------------------+
| Id | User | Host            | db   | Command | Time | State                   | Info             |
+----+------+-----------------+------+---------+------+-------------------------+------------------+
|  1 | root | localhost:5202  | test | Query   |    7 | Waiting for commit lock | commit           |
|  2 | root | localhost:14699 | test | Sleep   |   13 |                         | NULL             |
|  3 | root | localhost:17085 | NULL | Query   |    0 | init                    | show processlist |
+----+------+-----------------+------+---------+------+-------------------------+------------------+


分析

 flush table with read lock;持有(COMMIT,MDL_EXPLICIT,MDL_SHARED)

commit时上(COMMIT,MDL_EXPLICIT,MDL_INTENTION_EXCLUSIVE)锁

MDL_SHARED和MDL_INTENTION_EXCLUSIVE是不相容的,因此发生等待

3)Waiting for table metadata lock

这里我们来看第一节给出的锁等待的例子。

查询表时上(TABLE,MDL_TRANSACTION,MDL_SHARE_READ)锁,这里需注意MDL_TRANSACTION表示事物提交时才释放锁。

alter表上(TABLE,MDL_TRANSACTION, MDL_EXCLUSIVE)锁,MDL_SHARE_READ和MDL_EXCLUSIVE是不相容的,因此需等待查询事物提交。

metadata lock的更多相关文章

  1. mysql metadata lock(三)

    前言 MDL锁主要用来保护Mysql内部对象的元数据,通过MDL机制保证DDL与DML以及SELECT查询操作的并发.MySQL Meta Lock(一)和MySQL Meta Lock(二)已经讲了 ...

  2. mysql metadata lock(二)

    上一篇<mysql metadata lock(一)>介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问.本文将更详细的介绍MDL,主要 ...

  3. mysql metadata lock(一)

    想必玩过mysql的人对Waiting for table metadata lock肯定不会陌生,一般都是进行alter操作时被堵住了,导致了我们在show processlist 时,看到线程的状 ...

  4. MySQL出现Waiting for table metadata lock的原因以及解决方法

    转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for tab ...

  5. 【转】【MySql】Waiting for table metadata lock原因分析

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Wa ...

  6. mysql metadata lock锁

    很多情况下,很多问题从理论上或者管理上而言都是可以避免或者说很好解决的,但是一旦涉及到现实由于管理或者协调或者规范执行的不够到位,就会出现各种各样本不该出现的问题,这些问题的通常在生产环境并不会出现, ...

  7. Mysql事物与Metadata lock 问题

    环境说明:     MySQL 5.6.16     OS:Linux RedHat 6.2 64bit 1.问题描述 目前新上一个使用MySQL数据库项目,在数据库中,每隔5分钟做truncate某 ...

  8. 初步认知MySQL metadata lock(MDL)

    http://blog.itpub.net/26515977/viewspace-1208250/ 概述 随着5.5.3引入MDL,更多的Query被“Waiting for table metada ...

  9. Metadata Lock原理8

    http://www.kancloud.cn/taobaomysql/monthly/67141 MySQL· 5.7优化·Metadata Lock子系统的优化 背景 引入MDL锁的目的,最初是为了 ...

随机推荐

  1. poj 3067 Japan(线段树?,神奇卡时代码,暂未完)

    题目 //暴力的,没什么算法的,被琪琪视为傻逼的代码: //照者学长的神奇幸运卡时代码,虽然能AC,但是中途wa,tle了那么多次,啥也不想说了 //学长威武,能想出sum必须要是—— __int64 ...

  2. [C++]虚函数-同名访问

    首先来看一下派生类和基类成员同名事的处理规则: 派生类内定义了一个与基类同名的成员,该现象称为同名覆盖,此时,无论派生类内部成员函数还是派生类的对象访问同名成员,如果未加任何特殊标识,则访问派生类中重 ...

  3. linux设置和查看环境变量的方法

    1.    显示环境变量HOME $ echo $HOME /home/redbooks 2.    设置一个新的环境变量hello $ export HELLO="Hello!" ...

  4. lintcode :reverse integer 颠倒整数

    题目: 颠倒整数 将一个整数中的数字进行颠倒,当颠倒后的整数溢出时,返回 0 (标记为 32 位整数). 样例 给定 x = 123,返回 321 给定 x = -123,返回 -321 解题: 直接 ...

  5. java--依赖、关联、聚合和组合之间区别的理解

    在学习面向对象设计对象关系时,依赖.关联.聚合和组合这四种关系之间区别比较容易混淆.特别是后三种,仅仅是在语义上有所区别,所谓语义就是指上下文环境.特定情景等. 依赖(Dependency)关系是类与 ...

  6. JavaWeb项目开发案例精粹-第3章在线考试系统-003Dao层

    1. package com.sanqing.dao; import java.util.List; import com.sanqing.po.Student; public interface S ...

  7. Go语言博客

    http://www.cnblogs.com/concurrency/p/4293613.html#3130523

  8. liunx下tomcat启动报错

    liunx下tomcat启动 Cannot find ./catalina.sh 2013-08-23 11:50 1521人阅读 评论(0) 收藏 举报 Cannot find ./catalina ...

  9. jQuery通知插件 -- noty

    noty是一个jQuery的通知(信息提示)插件,灵活轻便,是一个非常棒的用于替代传统提示对话框的插件. 当前最新版本为2.1.0: 从https://github.com/needim/noty 可 ...

  10. PCL—低层次视觉—点云滤波(初步处理)

    点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之前必须要进行的预处理.其作用类似于信号处理中的滤波,但实现手段却和信号处理不一样.我认为原因有以下几个方面: ...