《Mysql 锁 - 概述》
一:锁类型(加锁范围区分类型)
- MySQL里面的锁可以分为:全局锁、表级锁、行级锁。
二:全局锁
- 作用
- 对整个数据库实例加锁。
- 加锁方式
- MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)
- 这个命令可以使整个库处于只读状态。
- 使用该命令之后,数据更新语句、数据定义语句和更新类事务的提交语句等操作都会被阻塞。
- 使用场景
- 全库逻辑备份。(加锁的目的是为了在备份时候 保证数据视图的一致性)
- 风险(指的使用全局锁风险)
- 如果在主库备份,在备份期间不能更新,业务暂停。
- 如果在从库备份,备份期间不能执行主库同步的binlog,导致主从延迟。
- 其他方法(可以代替全局锁的方法)
- 官方自带的逻辑备份工具mysqldump
- 当mysqldump使用参数--single-transaction的时候,会启动一个事务,确保拿到一致性视图。
- 而由于MVCC的支持,这个过程中数据是可以正常更新的。
- 一致性读是好,但是前提是引擎要支持这个隔离级别。
- 如果要全库只读,为什么不使用set global readonly=true的方式?
- 在有些系统中,readonly的值会被用来做其他逻辑,比如判断主备库。所以修改global变量的方式影响太大。
- 在异常处理机制上有差异。如果执行FTWRL命令之后由于客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态
- 而将整个库设置为readonly之后,如果客户端发生异常,则数据库就会一直保持readonly状态,这样会导致整个库长时间处于不可写状态,风险较高。
三:表级锁
- MySQL里面表级锁有两种
- 表锁(lock table)
- 元数据锁(meta data lock,MDL)
- 表锁
- 作用
- 防止 DDL 之间的冲突
- 加锁方式
- lock tables ... read/write
- 可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。
- 注意
- lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
- 例如:线程 A 执行了 lock tables t1 read, t2 write;
- 则其他线程写 t1、读写 t2 的语句都会被阻塞。
- 同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。
- 连写 t1 都不允许,自然也不能访问其他表。
- 元数据锁(MDL)
- 作用
- MDL作用是防止DDL和DML并发的冲突。
- 加锁方式
- 不需要显式使用,在访问一个表的时候会被自动加上。
- 在对一个表做增删改查操作的时候,加MDL读锁。(可并发读)
- 当要对表做结构变更操作的时候,加MDL写锁。(堵塞读写)
- 可能产生的问题
- 以下面的事务举例子
- 
- 分析一下上面事务可能产生的问题
- session A 先启动,这时候会对表 t 加一个 MDL 读锁。
- session B 需要的也是 MDL 读锁,因此可以正常执行。
- session C 会被 blocked(阻塞),是因为 session A 的 MDL 读锁还没有释放,而 session C 需要 MDL 写锁,因此只能被阻塞。
- 问题
- 如果只有 session C 自己被阻塞还没什么关系,但是之后所有要在表 t 上新申请 MDL 读锁的请求也会被 session C 阻塞。
- 因为 DML 的特性,所有对表的增删改查操作都需要先申请 MDL 读锁,就都被锁住,等于这个表现在完全不可读写了。
- 如果某个表上的查询语句频繁,而且客户端有重试机制,也就是说超时后会再起一个新 session 再请求的话,这个库的线程很快就会爆满。
- 原因
- 事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
- 解决热点更新表的字段添加问题?(知道 MDL 可能产生的问题,我们要尝试解决在热点表添加字段,同时避免 MDL 锁的问题)
- 应当尽量避免在业务高峰时,执行 DDL 语句
- 解决长事务 (事务不提交,就会一直占着 MDL 锁。)
- 在 MySQL 的 information_schema 库的 innodb_trx 表中,你可以查到当前执行中的事务。
- 如果你要做 DDL 变更的表刚好有长事务在执行,要考虑先暂停 DDL,或者 kill 掉这个长事务。
- 但是如果是热点表,请求频繁,而不得不加字段
- 这时候 kill 可能未必管用,因为新的请求马上就来了。
- 比较理想的机制是,在 alter table 语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到 MDL 写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。
- 之后开发人员或者 DBA 再通过重试命令重复这个过程。
四:行级锁
- 行级锁
- 是在各个 存储引擎里自己实现的。
- 两阶段锁的概念是什么? 对事务使用有什么帮助?
- 概念
- 在 InnoDB 事务中,行锁是在需要的时候才加上的(一段)。
- 但并不是不需要了就立刻释放, 而是要等到事务结束时才释放(二段)。
- 帮助
- 数据视图的一致性,保证隔离性。
- 死锁的概念是什么? 举例说明出现死锁的情况.
- 概念
- 事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。
- 死锁(A/B 事务相互等待)
A 事务 B 事务
update A = (A 加锁)
update B = (B 加锁)
update B = (等待B事务释放锁)
update A = (等待A事务释放锁)
死锁
- 死锁的处理策略?
- 死锁等待
- 当事务遇到死锁时候,会一直等待,直到超时。
- 参数 innodb_lock_wait_timeout 设置死锁等待时间(InnoDB默认是50s)。
- 死锁检测
- 当发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。
- 将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑(默认是开启状态)。
- 等待超时处理死锁的机制什么?有什么局限?
- 机制
- 出现死锁后,事务双方相互等待,直到有一个事务超时,另一个事务获得锁,继续执行。
- 局限
- 业务中出现大量的超时事务,而等待锁的过程中也会导致业务等待。
- 死锁检测处理死锁的机制是什么? 有什么局限?
- 机制
- 每当一个事务被锁的时候。就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。
- 局限
- 每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,这是一个时间复杂度是 O(n) 的操作。
- 假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。
- 虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源。因此,你就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。
- 有哪些思路可以解决热点更新导致的并发问题?(知道了死锁的机制处理之后)
- 如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关闭掉。
- 可能产生大量的超时事务,一般不建议采用
- 控制并发
- 根据上面的分析,你会发现如果并发能够控制住,比如同一行同时最多只有 10 个线程在更新,那么死锁检测的成本很低,就不会出现这个问题。
- 通过中间件或者其他方式,控制并发度,对应相同行的更新,在进入引擎之前排队。这样在InnoDB内部就不会有大量的死锁检测工作了。
- 业务拆分
- 比如把账单的一条数据,拆分成10条,最后求和。更新时候,选择一条进行操作。
- 这样可以减少锁冲突,并发度也会提高,但是业务复杂度可能会大大提高。
《Mysql 锁 - 概述》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- 【原创】go语言学习(十九)测试用例
目录 单元测试 压力测试 Go test命令介绍 单元测试 1.自动化测试框架 testingA. testing包提供了自动化测试相关的框架B. 支持单元测试和压力测试 import ( “test ...
- ROS参数服务器(Parameter Server)
操作演示,对参数服务器的理解:点击打开链接 rosparam使得我们能够存储并操作ROS 参数服务器(Parameter Server)上的数据.参数服务器能够存储整型.浮点.布尔.字符串.字典和列表 ...
- YII框架入门
一.安装 php运行环境安装包:http://www.phpstudy.net/a.php/207.html Yii安装包: https://github.com/yiisoft/yii2/relea ...
- QTP安装出现windoes installer不能安装升级修补程序问题
问题如下: windoes installer不能安装升级修补程序问题 如何解决?还未找到解决方案
- VMware安装Centos7超详细教程
本篇文章主要介绍了VMware安装Centos7超详细过程(图文),具有一定安装参考价值 在没有运维的情况下,很多时候测试需要自己搭建测试环境,而测试环境又分为QA环境,自动化测试环境,uat环境,以 ...
- hdu6468(记忆化搜索)
zyb的面试 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- Anriod手机抓包
1. 下载Fiddler http://fiddler2.com/ 2. 开启Fiddler的远程连接,Fiddler 主菜单 Tools -> Fiddler Options--> Co ...
- [mysql] Mysql数据分组GROUP BY 和HAVING,与WHERE组合使用
理解分组,可以这样:对GROUP BY子句后面跟随的列名进行分组,然后对每一个分组而不是整个表进行操作. 举例:在产品表中,检索每一个供应商提供的商品的数量. mysql> SELECT ven ...
- 2018-2019-2 《网络对抗技术》 Exp7 网络欺诈防范 20165222
1.实践目标 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法. 2.实践内容 (1)简单应用SET工具建立冒名网站 (1分) apachectl start开启服务 ser ...
- 2018-2019-2 20165234 《网络对抗技术》 Exp8 网络欺诈防范 Web基础
Exp8 网络欺诈防范 Web基础 一. 实践内容 1. Web前端HTML 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML. 2. Web ...