zoukankan      html  css  js  c++  java
  • MDL锁获取顺序和优先先

    官方文档:

    https://dev.mysql.com/doc/refman/5.7/en/metadata-locking.html

    如果给定的锁有多个等待者,则满足最高优先级的锁请求,写锁请求的优先级高于读锁请求。

    但是,如果 max_write_lock_count设置为某个较低的值(比如 10),如果读锁请求已经被传递给 10 个写锁请求,那么读锁请求可能比挂起的写锁请求更受欢迎。通常不会发生此行为,因为 max_write_lock_count默认情况下具有非常大的值。

    语句是一个一个获取元数据锁,而不是同时获取元数据锁,并在进程中进行死锁检测。

    DML语句通常按语句中提到的表的顺序获取锁。

    DDL语句,LOCK TABLE语句和其它类似语句,是按照表名称顺序来获取元数据锁,对于隐式使用的表(比如外键),可能会以不同的顺序获取锁。

    例如,RENAME TABLE是一个按照表名称获取锁的DDL语句。

    RENAME TABLE语句重命名tbla为tbld表,tblc重命名为 tbla

    RENAME TABLE tbla TO tbld, tblc TO tbla;

    该语句获取元数据锁的顺序是tbla tblc tbld,(因为按名称排序,tbld在tblc后边)

    这个RENAME TABLE语句将 tbla 重命名为tblb,  将 tblc 重命名为 tbla

    RENAME TABLE tbla TO tblb, tblc TO tbla;

    这种情况下,获取元数据锁的顺序是 tbla   ,   tblb   ,   tblc   (因为按名称排序,tblb 在 tblc 前边)

    当多个事务并发执行时,元数据锁获取顺序会影响操作结果,如下所示,

    x 和 x_new 两个表具有相同的表结构,三个客户端同时发出这些语句。

    先创建 x 和 x_new 表

    mysql> create table x (id int primary key);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table x_new like x;
    Query OK, 0 rows affected (0.01 sec)

    session1:

    LOCK TABLE x WRITE, x_new WRITE;

    session2(进行锁等待状态):

    mysql> INSERT INTO x VALUES(1);

    session3(进行锁等待状态):

    注意:加锁顺序是 x , x_new , x_old ,在对 x 表加锁时就遇到了锁等待,所以还没有对 x_new , x_old 表申请加锁。

    mysql> RENAME TABLE x TO x_old, x_new TO x;

    session1(释放 x , x_new 表锁):

    mysql> unlock tables;
    Query OK, 0 rows affected (0.00 sec)

    session1释放锁资源后, session2 并没有最先获取到 x 表的元数据写锁请求,

    session3 请求的是排它锁,排它锁优先级高于写锁请求,所以session3 拿到排它锁,再释放之后,session2才会到到 x 表的写锁请求。

    session3获取锁的顺序是 x , x_new , x_old

    RENAME TABLE 操作在 INSERT 之前进行了。

    也就是说执行顺序是session1 --> session3  --> session2

    gh-ost 软件在最后的切表阶段,就很精妙的利用了Mysql这个特性。

    gh-ost原理:https://zhuanlan.zhihu.com/p/83771721

    mysql> select * from x;
    +----+
    | id |
    +----+
    |  1 |
    +----+
    1 row in set (0.00 sec)
    
    mysql> select * from x_old;
    Empty set (0.00 sec)

    实验2:创建x , new_x 表,

    创建测试表

    mysql> drop table x,x_old;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table x(id int primary key);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table new_x like x;
    Query OK, 0 rows affected (0.01 sec)

    同样三个客户端发起相同的SQL语句。

    session1:

    LOCK TABLE x WRITE, new_x WRITE;

    session2(进行锁等待状态):

    mysql> INSERT INTO x VALUES(1);

    session3(进行锁等待状态):

    注意:加锁顺序是 new_x , old_x ,x 在对 new_x 表加锁时就遇到了锁等待,所以还没有对 old_x , x 表申请加锁。

    mysql> RENAME TABLE x TO old_x, new_x TO x;

    session1(释放 x , new_x 表锁):

    mysql> unlock tables;
    Query OK, 0 rows affected (0.00 sec)

    session1释放 x , new_x 锁资源,

    对于 x 表,只有session2 在等待获取锁,所以sesion1 释放锁资源后,session2会马上拿到锁资源,

    对于 new_x 表,只有 session3  在等待获取锁,但 session3 不止要获取 new_x 表上的锁,还要获取 old_x , x 表上的锁。

    其实,session2 在插入未完成之前,不会释放x 表锁,RENAME TABLE操作还是会处理锁等待状态。

    mysql> SELECT * FROM x;
    Empty set (0.01 sec)
    
    mysql> SELECT * FROM old_x;
    +------+
    | i    |
    +------+
    |    1 |
    +------+

    如果并发语句中的锁获取顺序对操作结果的应用程序产生影响,如前面的示例,您可以调整表名以影响锁获取的顺序。

     
  • 相关阅读:
    Python零基础入门的基础案例
    今天不抠图,Python实现一键换底片!想换什么换什么(附源码)
    python基础:如何使用 pip 安装第三方库
    Python教程:matplotlib 绘制双Y轴曲线图
    福利来啦,送给大家一个小游戏的源码,不要错过哟
    招聘信息太多,哪家职位才是适合你的?Python采集招聘信息
    我的python菜鸟之路1
    我的SAS菜鸟之路3
    我的SAS菜鸟之路2
    猪鹿蝶1
  • 原文地址:https://www.cnblogs.com/nanxiang/p/15206646.html
Copyright © 2011-2022 走看看