| |
|
开发:
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提供了一个加全局读锁的方法,命令:
当需要让整个库处于只读状态时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。 全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表都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事务中,行锁是在需要的时候才加上的,但并不是不需要就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。那对我们有什么帮助呢??如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。 死锁和死锁检测 当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会 导致这几个线程都进入无限等待的状态,称为死锁。 当出现死锁以后,两种策略:
第一种策略不是很优雅,默认时长50s,对于线上服务,这个等待时间无法接受,如果时间设置过小,发生死锁确实很快可以解开,但是会出现很多误伤。所以正常情况下,还是要采用第二种策略:主动死锁检测。主动死锁检测在发生死锁的时候,是能快速发现处理的,但是有额外负担。也就是每当一个事务被锁就要检测所依赖的线程有没有被锁住;每新来被堵住的线程都要判断自己加入会不会导致死锁,这是个时间复杂度O(n)的操作,要消耗大量的CPU资源。怎么解决这种热点行更新导致的性能问题呢???
行锁防止别的事务修改或删除,GAP锁防止别的事务新增,行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的幻读问题。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |