mysql-锁

 2023-09-15 阅读 25 评论 0

摘要:根据加锁的范围,MySQL里面的锁大致可以分为全局锁、表级锁和行锁三类。 全局锁 全局锁是对整个数据库实例加锁。MySQL提供了一个加全局读锁的方法,命令: Flush tables with read lock (FTWRL) 当需要让整个库处于只读状态时候,可以使用这个命令&#

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

全局锁

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

Flush tables with read lock (FTWRL)

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

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

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

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

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

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

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

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

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

表级锁

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

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

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

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

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

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

mysql缩表?是太大。

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

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

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

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

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

mysql锁库?

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

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

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

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

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

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

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

行锁

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

两阶段锁

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

mysql的锁有几种,

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

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

死锁和死锁检测

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

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

mysql事务锁、当出现死锁以后,两种策略:

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

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

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

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

mysql查看锁,

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/60703.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息