首页 > 数据库 >MySQL锁

MySQL锁

时间:2024-07-06 16:21:52浏览次数:8  
标签:语句 事务 MDL 读锁 session MySQL

MySQL锁

1.前言

锁是计算机在执行多线程或线程时用于并发访问同一共享资源时的同步机制,MySQL中的锁是在服务器层或者存储引擎层实现的,保证了数据访问的一致性与有效性

MySQL锁可以按模式分类为:乐观锁与悲观锁。按粒度分可以分为全局锁、表级锁、页级锁、行级锁。按属性可以分为:共享锁、排它锁。按状态分为:意向共享锁、意向排它锁。按算法分为:间隙锁、临键锁、记录锁

img

2. 锁类型

2.1.全局锁

(1) 概念

全局锁就是对整个数据库实例加锁

(2) 应用场景

全库逻辑备份(mysqldump)

(3) 实现方式

MySQL 提供了一个加全局读锁的方法,命令是Flush tables with read lock (FTWRL)

当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

风险点:

如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就能停止

如果在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟

解决办法:

mysqldump使用参数--single-transaction,启动一个事务,确保拿到一致性视图。而由于MVCC的支持,这个过程中数据是可以正常更新的

2. 表级锁

(1) 概念

当前操作的整张表加锁,最常使用的 MyISAM 与 InnoDB 都支持表级锁定

MySQL 里面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)

(2) 实现方式

表锁:lock tables … read/write;

例如lock tables t1 read, t2 write; 命令,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能在unlock tables之前访问其他表。

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

(3) 风险点

参考于:www.cnblogs.com/keme/p/1106…

给一个表加字段,或者修改字段,或者加索引,需要扫描全表的数据。在对大表操作的时候,肯定会特别小心,以免对线上服务造成影响。而实际上,即使是小表,操作不慎也会出问题

sessionA:
begin;
select * from t limit 1;
2. sessionB:

select from t limit 1;
3. sessionC:
alter table t add f int;

\# 会mdl锁住
4. sessionD:

select from t limit 1;

我们可以看到 session A 先启动,这时候会对表 t 加一个 MDL 读锁。由于session B 需要的也是 MDL 读锁,因此可以正常执行

之后 session C 会被 blocked,是因为 session A 的 MDL 读锁还没有释放,而 sessionC 需要MDL 写锁,因此只能被阻塞

如果只有 session C 自己被阻塞还没什么关系,但是之后所有要在表 t 上新申请 MDL 读锁的请求也会被session C 阻塞。前面说了,所有对表的增删改查操作都需要先申请MDL 读锁,而这时读锁没有释放,对表alter ,产生了mdl写锁,把表t锁住了,这时候就对表t完全不可读写了

如果某个表上的查询语句频繁,而且客户端有重试机制,也就是说超时后会再起一个新session 再请求的话,这个库的线程很快就会爆满

事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
注:一般行锁都有锁超时时间。但是MDL锁没有超时时间的限制,只要事务没有提交就会一直锁注

(4) 解决办法

首先我们要解决长事务,事务不提交,就会一直占着 MDL 锁。在 MySQL 的information_schema 库的 innodb_trx 表中,你可以查到当前执行中的事务。如果你要做 DDL 变更的表刚好有长事务在执行,要考虑先暂停 DDL,或者 kill 掉这个长事务。这也是为什么需要在低峰期做ddl 变更

标签:语句,事务,MDL,读锁,session,MySQL
From: https://www.cnblogs.com/zhangyf1121/p/18287375

相关文章

  • MySQL日志
    MySQL日志1.MySQL六种日志:重做日志(redolog)回滚日志(undolog)归档日志(binlog)错误日志(errorlog)慢查询日志(slowquerylog)一般查询日志(generallog)中继日志(relaylog)对MySQL来说,逻辑备份日志(binlog)、重做日志(redolog)、回滚日志(undolog)、锁技术+MVCC原子性:通过undolog......
  • centos7服务器yum安装MySQL数据库,以及报错的解决方案
    文章目录1、数据库能做什么?2、数据库由来3、数据库-系统结构4、版本二、部署1、官网地址3.点击[DOCUMENTATION](https://dev.mysql.com/doc/)4.mysql的yum仓库[UsingtheMySQLYumRepository](https://dev.mysql.com/doc/refman/8.4/en/linux-installation-yum-repo......
  • 零基础学习MySQL---表的相关操作
    顾得泉:个人主页个人专栏:《Linux操作系统》 《C++从入门到精通》  《LeedCode刷题》键盘敲烂,年薪百万!一、创建表1.语法CREATETABLEtable_name(field1datatype,field2datatype,field3datatype)characterset字符集collate校验规则engine存......
  • Java面试八股之MySQL存储引擎都有哪些
    MySQL存储引擎都有哪些MySQL提供了多种存储引擎,每种引擎都有其独特的特性和用途。以下是一些常用的MySQL存储引擎:InnoDB默认存储引擎(自MySQL5.5版本起)。支持事务(ACID属性)、行级锁定和外键约束。使用B+树作为索引结构。适合需要高并发的事务处理和高可靠性的场景。MyISA......
  • MySQL 命名使用规范
    在数据库设计和开发过程中,命名规范是确保数据库结构清晰、易于维护和扩展的关键因素之一。良好的命名规范可以提高代码的可读性、可维护性和团队协作效率。本文将详细介绍MySQL数据库的命名使用规范,包括数据库、表、列、索引、约束、存储过程、函数、视图和触发器等方面的命名......
  • Mysql 索引
     在MySQL中,索引是一种数据结构,它能够帮助快速查找和检索表中的记录,从而提高查询性能。索引在数据库中类似于书籍的目录,可以快速定位到所需的内容。下面是关于MySQL索引的详细介绍,包括其概念、类型、如何使用以及如何在建表时指定索引。什么是索引索引是存储在数据库中的一......
  • Mysql 8.4 安装(Centos7.9)
    前置准备root环境下执行#关闭selinuxvi/etc/selinux/config#SELINUX=enforcing=>SELINUX=disabled#开通防火墙3306/tcpfirewall-cmd--permanent--add-port=3306/tcp下载链接获取https://dev.mysql.com/downloads/file/?id=529414下载&安装下载mkdir-p......
  • mysql 模糊查询
     _表示单个字符SELECT*FROMemployeesWHEREfirst_nameLIKE"___e%";SELECT*FROMemployeesWHEREfirst_nameLIKE"____";查询以J开头,a结尾SELECT*FROMemployeesWHEREfirst_nameLIKE"J%";SELECT*FROMemployeesWHEREfirst_name......
  • linux下mysql安装、授权、创建用户、连接navicat、连接entity
    1.linux下安装mysql:sudoapt-getupdatesudoapt-getinstallmysql-serversudosystemctlstartmysqlsudomysql_secure_installation#这一步不是必须的,甚至有害的2.授权usemysql;updateusersethost='%'whereuser='root';flushprivileges;grantall......
  • MySQL 字符串日期格式转换
    在MySQL中,经常需要将字符串类型的日期转换成日期或时间类型,或者在不同的日期格式之间进行转换。MySQL提供了几种方法来实现这一点,包括使用STR_TO_DATE()和DATE_FORMAT()函数。1.使用STR_TO_DATE()函数STR_TO_DATE()函数可以将字符串转换成日期或时间格式。它接受两个主要参......