其他分享
首页 > 其他分享> > 全局锁、表锁

全局锁、表锁

作者:互联网

全局锁

全局锁的典型使用场景是,做全库逻辑备份
历史做法:flush table with read lock;确保不会有其他线程对数据库做更新,然后对整个库做备份。

mysql> flush table with read lock;
Query OK, 0 rows affected (0.10 sec)

mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  5 |    5 |    5 |
| 10 |   10 |   55 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
+----+------+------+
6 rows in set (0.01 sec)

mysql> update d set d = 99 where id = 0;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock

缺陷:

官方自带的逻辑备份工具是 mysqldump,mysqldump 使用参数–single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。

能够支持事务隔离的,就可以通过事务隔离的手段来做到,有的引擎不支持(如:MyISAM不支持),需要通过FTWRL来给全局上锁

为什么不用set global readonly=true?

表级锁

表锁

语法:lock tables … read/write
解除:unlock tables

写锁(排他锁):自己能写
读锁(共享锁):都能读,不能写
在这里插入图片描述
对于 InnoDB 这种支持行锁的引擎,一般不使用 lock tables 命令来控制并发,毕竟锁住整个表的影响面还是太大。

MDL(metadata lock)

MDL(MySQL 5.5 版本中引入) 的作用是,保证读写的正确性,MDL 不需要显式使用,在访问一个表的时候会被自动加上。

读锁与读锁止键不互斥,写锁与写锁,读锁与写锁之间互斥,用来保证变更表结构操作的安全性

注意安全性:
在这里插入图片描述
在这里插入图片描述
session A 先启动,这时候会对表 t 加一个 MDL 读锁。
session B 需要的也是 MDL 读锁,因此可以正常执行。
session C 会被 blocked,是因为 session A 的 MDL 读锁还没有释放。session D 也会被 blocked。

导致问题:如果查询语句频繁,且客户端有重试机制会打爆Mysql
结论:事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放

如何安全地给小表加字段?

  1. information_schema 库的 innodb_trx 表中如果有长事务,暂停 DDL,或者 kill 掉这个长事务。
  2. alter table 语句里面设定等待时间。(如果在这个指定的等待时间里面能够拿到 MDL 写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后开发人员或者 DBA 再通过重试命令重复这个过程)思想:防止死锁,加入超时时间机制

MariaDB 已经合并了 AliSQL 的这个功能,所以这两个开源分支目前都支持 DDL NOWAIT/WAIT n 这个语法

ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ... 

MySQL 8.0.1在select语法中给出了NOWAIT特性(官方博客),也就是我们可以在查询时如果需要等待行锁,则立即退出报错。这种特性其实也可以用在MDL锁,这样我们如果在进行DDL语句时,通过NOWAIT检测一下是否有相关元数据锁等待,如果有则立即退出,这样运维人员即可及时判断出能否进行ddl操作,而不至于在执行ddl时,造成大量业务中断。
在这里插入图片描述

标签:语句,事务,MDL,lock,读锁,session,全局,表锁
来源: https://blog.csdn.net/qq_42239520/article/details/122297431