IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> mysql-锁 -> 正文阅读

[大数据]mysql-锁

根据加锁的范围,MySQL里面的锁大致可以分为全局锁、表级锁和行锁三类。

全局锁

全局锁是对整个数据库实例加锁。MySQL提供了一个加全局读锁的方法,命令:

Flush tables with read lock (FTWRL)

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

全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表都select出来存成文本。

官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数–single-transaction

的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,

这个过程中数据是可以正常更新的。

你可能疑惑,有了官方自带的,为啥还要(FTWRL)呢??一致性读是好,但前提是引擎要支持这个隔离级别。对于不支持事务的引擎,如果备份中有更新,就会获取最新数据,破坏备份一致性。就需要使用FTWRL命令。

所以,single-transaction 方法只适用于所有的表使用事务引擎的库。如果有的表使用了

不支持事务的引擎,那么备份就只能通过 FTWRL 方法。这往往是 DBA 要求业务开发人员

使用 InnoDB 替代 MyISAM 的原因之一。

表级锁

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

表锁的语法是 lock tables … read/write。与 FTWRL 类似,可以用 unlock tables 主动

释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables 语法除了会限制别

的线程的读写外,也限定了本线程接下来的操作对象。

在还没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式。而对于 InnoDB 这

种支持行锁的引擎,一般不使用 lock tables 命令来控制并发,毕竟锁住整个表的影响面还

是太大。

另一类表级的锁是MDL(meta data lock)。MDL 不需要显式使用,在访问一个表的时候

会被自动加上。MDL 的作用是,保证读写的正确性。

在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL

读锁;当要对表做结构变更操作的时候,加 MDL 写锁。读读不互斥;读写、写写互斥;

MDL作用是防止DDL和DML并发的冲突。

事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。【长事务】

seasonA 开启事务没有进行关闭,模拟长事务。

对于大表DDL,大家一般都比较谨慎,而对于小表,就会比较随意。基于上面分析,讨论下如何安全地给小表加字段???

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

如果要变更的表是一个热点表,数据量不大但是请求很频繁,kill未必管用,比较理想的机制是,在 alter table语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到 MDL 写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后开发人员或者 DBA 再通过重试命令重复这个过程。

另外,尽量保证表结构变更在数据库流量低峰期操作,比如夜间,这样能更好的避免出现风险。

  • 避免长事务
  • 在流量低峰期进行

行锁

MySQL行锁是在引擎层由各个引擎自己实现的。并不是所有的引擎都支持行锁。不支持行锁意味着并发控制只能使用表锁,这就会影响业务并发度。

两阶段锁

如下图事务B的update语句执行时会是什么现象?id是主键

实际上事务B的update语句会被阻塞,直到事务A执行commit之后,事务B才能继续执行。

这是因为事务A持有两个记录的行锁,都是在commit的时候才释放的。也就是说,在InnoDB事务中,行锁是在需要的时候才加上的,但并不是不需要就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。那对我们有什么帮助呢??如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

死锁和死锁检测

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会

导致这几个线程都进入无限等待的状态,称为死锁

当出现死锁以后,两种策略:

  1. 一种是直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置。
  2. 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。

第一种策略不是很优雅,默认时长50s,对于线上服务,这个等待时间无法接受,如果时间设置过小,发生死锁确实很快可以解开,但是会出现很多误伤。所以正常情况下,还是要采用第二种策略:主动死锁检测。主动死锁检测在发生死锁的时候,是能快速发现处理的,但是有额外负担。也就是每当一个事务被锁就要检测所依赖的线程有没有被锁住;每新来被堵住的线程都要判断自己加入会不会导致死锁,这是个时间复杂度O(n)的操作,要消耗大量的CPU资源。怎么解决这种热点行更新导致的性能问题呢???

  1. 如果能确保业务不会出现死锁,可以临时把死锁检测关掉
  2. 控制并发度
  3. 可以考虑通过将一行改成逻辑上的多行来减少锁冲突

行锁防止别的事务修改或删除,GAP锁防止别的事务新增,行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的幻读问题。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-24 10:37:42  更:2021-09-24 10:39:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:04:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码