MySQL的锁机制之全局锁和表锁的实现

 更新时间:2023年01月15日 09:00:55   作者:恒者走天下  
本文主要介绍了MySQL的锁机制之全局锁和表锁的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

对mysql锁的总结学习,本文将围绕,加锁的概念,加锁的应用场景和优化,以及不加锁会导致的问题这些方向进行总结学习。mysql的全局锁和表锁是本文的重点

一、全局锁

全局锁的介绍以及使用

全局锁就是对整个数据库实例进行加锁。
MySQL提供了一个加全局读锁的方法,如下:
全局读锁定:

FLUSH TABLES WITH READ LOCK ;

执行了命令之后所有库所有表都被锁定只读,解锁:

UNLOCK TABLES ;

加了全局读锁之后,整个数据库都处于只读的状态,当其他线程有数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新事务的提交语句都将会被阻塞。

全局锁的应用场景

了解了全局锁的基本概念后,心想全局锁的锁粒度这么大,效率肯定特别低,应该很少使用吧。但是开发者设计出来这个,肯定有它的使用场景啊。接下来我们看下:
通过学习了解到,全局锁最经典最常用的场景是用做全库逻辑备份 (就是把整个库的每个表select出来存放成文本)
把整个数据库都锁住,不能有更新操作,想想都危险,锁的粒度太大了。
比如:
如果在用户访问高峰期,这期间需要数据库的有关表进行更新操作。这是如果你备份整个库是在主库上备份,那么备份期间都不能执行更新操作,这是业务基本上就得停摆,影响用户体验。而如果你选择在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟。

此时,你肯定想那加锁这么麻烦危险,那还不如不加锁呢。如果不加锁会导致什么后果呢

不加锁导致的危害

这里我举个简单的购物例子,你就瞬间清楚了。
比如,购物。我在某网站上买了一件商品,同时维护这网站的也准备发起一个数据库的逻辑备份。
如果时间顺序上是先备份我们用户的账号余额表,然后用户购买,然后备份用户商品表。
此时,会出现什么问题呢。结果会发现,我们用户的账号余额没减少,但是多了件购买的商品。这也是不是感觉挺好,我们用户赚大了啊。不过如果反过来呢,那我们岂不是亏大了。

反观,会出现这么一个现象的原因是什么,其实就是备份的库,备份的库中的表不是一个逻辑时间点的,即前后没有一致性。

提到一致性,我们会想到那不直接在可重读隔离级别下开启一个事务,进行数据逻辑备份不就好了吗,那岂不是比加锁好。

想法挺好的,但是也需要系统支持啊。比如像MyISAM这种不支持事务的引擎,只能通过FTWRL方法了。

加锁和其他方法对比

通过上面可以知道,整个库进行备份,就是先把整个库通过加全局读锁,把整个库设置成只读状态。
此时,你肯定会想,把整个库设置成只读状态,我还知道使用如下命令进行设置啊,不必要加锁啊

set global readonly=true;

确实,readonly这种方式也可以让全库进入只读状态。但是对于一些特殊情况,如在异常处理机制上,如果执行FTWRL命令之后,客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态,而将这个库设置为readonly之后,如果客户端发生异常,则数据库就会一直保持readonly状态,这样会导致整个库长时间处于不可写状态;所以还是建议使用全局锁比较合适

了解完了全局锁,接下来我们再来学习以下表锁

二、表锁

表锁的介绍以及使用

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

对于表锁,加锁的语句是:

LOCK TABLES tbl_name ; #不影响其他表的写操作

解锁的语句是:

UNLOCK TABLES ;

另一类表级的锁是 MDL(metadata lock) 。MDL不需要显式使用,在访问一个表的时候会被自动加上。

表锁的应用场景

针对表锁,在MySQL发展初级阶段,没有设计出更细粒度的锁时,表锁经常被用于处理并发(InnoDB支持行锁所以一般不会使用表锁)。举个例子,如果在某个线程A中执行lock tables t1 read, t2 write;这个语句,则其他线程写t1、读写t2的语句都会被阻塞。同时,线程A在执行unlock table之前,也只能执行读t1、读写t2的操作。连写t1都不允许,自然也不能访问其他表。

对于MDL锁,是访问一个表的时候自动加上的。为什么呢,这也是因为时间逻辑点的不同。比如,如果一个查询正在遍历一个表中的数据,而在此执行期间另一个线程对这个表结构做变更,删了一列,那么查询线程拿到的结果跟表结构对不上,就会出错。为此,为了解决这些问题。当对一个表做增删改查操作的时候,加MDL读锁;要对表做结构变更操作的时候,加MDL写锁。

为此需要注意的还有一点,并不是系统默认为每一访问表的操作自动添加了MDL锁就会万事大吉。比如,对于一个表t执行如下的操作:

在这里插入图片描述

session A先启动,对表t加一个MDL读锁
因为session B需要的也是读锁,可以正常执行
因为session A的MDL读锁还没有释放,而session C需要MDL写锁,因此会被阻塞
session C之后的所有要对表申请的读锁页会被session C阻塞,最终导致这个表完全不可读写
此时如果对这个表的查询比较频繁,并且客户端也有重试机制,那么这个库的线程很快就会爆满

造成这个问题的原因是,事务中的MDL锁,在执行语句的时候开始申请,但是语句结束后并不会马上释放,而是等到整个事务提交后再释放。

因此,了解了这个问题,以及这个问题出现的原因。
那么我们如何解决安全的给表加字段呢

首先要解决长事务,毕竟事务不提交,就会一直占着MDL锁。。因此如果要做DDL变更表的时候,查到刚好有长事务在执行,可以考虑暂停DDL操作或者kill掉长事务
如果要操作的表是个热点表,请求比较频繁,此时如果采用kill,那么新的请求立马就来了,未必管用。因此比较合适的操作是:在alter table语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到MDL写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后再通过重试命令重复这个过程。

到此这篇关于MySQL的锁机制之全局锁和表锁的实现的文章就介绍到这了,更多相关MySQL 全局锁和表锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL实例精讲单行函数以及字符数学日期流程控制

    MySQL实例精讲单行函数以及字符数学日期流程控制

    SQL函数即数据库的内置函数,可以运用在SQL语句中实现特定的功能。SQL单行函数对于每一行数据进行计算后得到一行输出结果。SQL单行函数根据数据类型分为字符函数、数字函数、日期函数、转换函数,另外还有一些别的函数
    2021-10-10
  • 一次MySQL启动导致的事故实战记录

    一次MySQL启动导致的事故实战记录

    这篇文章主要给大家介绍了一次MySQL启动导致的事故实战记录,记录了MySQL 启动成功但未监听端口的解决方法,文中给出了详细的解决方法,需要的朋友可以参考下
    2021-09-09
  • mysql之数字函数的具体使用

    mysql之数字函数的具体使用

    本文主要介绍了mysql之数字函数的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • MySQL+Navicat安装配置保姆级教程

    MySQL+Navicat安装配置保姆级教程

    这篇文章主要介绍了MySQL+Navicat安装配置教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-05-05
  • mysql实现按照某个时间段分组统计

    mysql实现按照某个时间段分组统计

    这篇文章主要介绍了mysql实现按照某个时间段分组统计方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • mysql5.1.26安装配置方法详解

    mysql5.1.26安装配置方法详解

    这篇文章主要为大家详细介绍了mysql安装配置方法,图文详解MySQL5.1.26安装步骤,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • 初始化MySQL用户(删除匿名用户)

    初始化MySQL用户(删除匿名用户)

    安装完MySQL后,系统默认会创建一个不需要密码的root用户,和一个无用户名无密码的匿名用户(Anonymous Account)。进行下面的初始化操作以合理授权,增强安全
    2016-01-01
  • MyISAM和InnoDB引擎优化分析

    MyISAM和InnoDB引擎优化分析

    这几天在学习mysql数据库的优化并在自己的服务器上进行设置,喻名堂主要学习了MyISAM和InnoDB两种引擎的优化方法,需要了解跟多的朋友可以参考下
    2012-11-11
  • 经测试最好用的mysql密码忘记的解决方法

    经测试最好用的mysql密码忘记的解决方法

    经测试最好用的mysql密码忘记的解决方法...
    2007-06-06
  • 一文详解MySQL text能存多少个字符

    一文详解MySQL text能存多少个字符

    在我们使用mysql的时候,对字段的选用以及具体使用什么类型会很有疑问,下面这篇文章主要给大家介绍了关于MySQL text能存多少个字符的相关资料,需要的朋友可以参考下
    2023-01-01

最新评论