MySQL 锁机制

本文深入解析MySQL中的锁机制,包括全局锁、表级锁、行锁及死锁检测等内容,探讨了不同锁类型的特点和应用场景,如FTWRL用于全库备份,MDL保证读写正确性,以及行锁的两阶段锁协议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


MySql 锁设计是为了处理并发问题,作为多用户共享资源,当出现并发访问的时候,数据库要合理的控制资源访问规则。而锁就是用来实现这些访问规则的。

MySql 锁设计是为了处理并发问题,作为多用户共享资源,当出现并发访问的时候,数据库要合理的控制资源访问规则。而锁就是用来实现这些访问规则的。

全局锁

含义:对整个数据库实例进行加锁。

方式:MySQL 提供了一个加全局读锁的方法,命令是 Flush table with read lock(FTWRL) ,使用该命令,之后的以下线程语句都会被阻塞:

  • 数据更新(数据增删改)
  • 数据定义(建表、改表结构)
  • 更新事务提交语句

场景:做全库备份。也就是把整个表 select 出来存成文本。通过 FTWRL 确保不会有其他线程对数据库做更新,整个库成为只读状态。

注意

  • 在主库备份,备份期间不能执行更新。业务基本停摆。
  • 从库备份,期间无法与主库同步过来 binlog,会导致主从延迟。

其他方式:可以采用事务隔离,事务隔离级别的可重复读,在事务开始的时候,可以拿到一致性的视图,接下来所读的数据都是一样的,由于 MVCC 支持,过程中数据可以正常更新。

MySQL 官方自带的逻辑备份工具是 mysqldump,使用 single-transaction 参数,导数据前会启动一个事务,确保拿到一致性视图,而且由于 MVCC 支持,过程中数据可以正常更新。

前提是数据库引擎支持这个隔离级别。

如果设置全库只读?

命令 set global readonly=true ,可以进入全库只读,但是不建议,不如用 FTWRL,原有:

  1. readonly 可以被用来做其他逻辑,比如用来判断一个库是主库还是从库
  2. 如果客户端突然端口,如果是 FTWRL ,MySQL 会自动释放全局锁,整个库回到正常更新状态。如果是 readonly,客户端发送一次,数据库则保持 readonly,导致整个库长时间不可写,风险高。

表级锁

种类

  1. 表锁
  2. 元数据锁(metadata lock,MDL)

表锁

语法lock table ... read/write ,和 FTWRL 类似,unlock tables 可以用来主动释放锁,可以在客户端断开时自动释放。但是限制了本线程接下来的操作:

  • 对于线程 A 中执行 lock tables t1 read、t2 write。其他线程写 t1 、读写 t2 会被阻塞,同时线程 A 执行 unlock tables 之前,也只能执行读 t1、读写 t2 操作,连写 t1 也不写,也不能来访问其他表。

但是表锁锁住整个表,影响范围大,一般不适用 lock tables 命令来控制并发。

MDL(metadata lock)

在 MySQL 5.5 版本中引入 MDL,不需要显示使用,在访问一个表的时候,会自动加上。

作用:保证读写正确性。

  • 当对一个表做增删改查,加 MDL 读锁
  • 对表结构操作,加 MDL 写锁。
  • 读锁之间不互斥,多个线程可以同时对一张表增删改查。
  • 读写锁、写锁之间互斥。保证变更表结构的安全性,如果有两个线程同时对一个表加字段,其中一个要等另一个执行完毕才开始。

注意:MDL 会直到事务提交才释放,表结构改变的时候,要小心避免锁住线上的查询和更新。

行锁

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

建议:

如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

死锁和死锁检测

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。

解决死锁的策略

  1. 直接进入等等,直到超时,超时时间可以通过 innodb_lock_wait_timeout 设置。
  2. 发起死锁检查,发现死锁后主动回滚死锁链中某一个事务。让其他事务继续执行,将参数 innodb_deadlock_detect设置为 on。

两个策略缺点:

  1. innodb_lock_wait_timeout 默认为 50 s,意味者如果采用的话,第一个锁住的线程 50 s 后才会超时退出。其他线程继续。对于在线服务难以接受。但是如果时间太短,又很容易误伤
  2. 死锁检查需要一定的负担,每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。

如何解决热点行更新导致的性能问题?

  • 如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关闭掉。一般不建议采用
  • 控制并发度,对应相同行的更新,在进入引擎之前排队。这样在InnoDB内部就不会有大量的死锁检测工作了。
  • 将热更新的行数据拆分成逻辑上的多行来减少锁冲突,但是业务复杂度可能会大大提高。比如账户余额,分为多行数据,需要的时候求总数即可,但是插入的时候代码的逻辑要稍稍改变。

注意:innodb行级锁是通过锁索引记录实现的,如果更新的列没建索引是会锁住整个表的。

Visual Studio Code 是由微软开发的一款免费、开源、跨平台的现代化轻量级代码编辑器,自发布以来迅速成为全球开发者最受欢迎的工具之一。它结合了编辑器的轻便性和集成开发环境(IDE)的强大功能,支持多种编程语言和开发场景,核心特点: 1. 跨平台支持 可在 Windows、macOS 和 Linux 上运行,保持一致的用户体验。 2. 轻量级与高性能 启动速度快,占用资源少,适合处理大型项目或低配置设备。 3. 智能代码补全 内置 IntelliSense(智能感知),提供代码提示、参数信息、快速修复等功能,支持 JavaScript、TypeScript、Python、C++ 等主流语言。 4. 内置终端 直接在编辑器内打开集成终端(支持 PowerShell、CMD、Bash 等),方便执行命令行操作。 5. 调试工具 内置调试器,支持断点、变量监视、调用堆栈查看等,无需离开编辑器即可调试代码。 6. Git 集成 直接通过侧边栏管理 Git 仓库,支持提交、分支切换、冲突解决等操作。 7. 丰富的扩展生态系统 通过 Extensions Marketplace 可安装数千款插件,扩展功能包括: 语言支持:如 Java、Go、Rust 等。 主题与图标:自定义界面风格。 工具集成:如 Docker、Kubernetes、数据库连接等。 效率工具:如 REST Client、Live Server 等。 8. 自定义与主题 支持修改键盘快捷键、界面主题、文件图标等,打造个性化开发环境。 9. 多光标编辑 按住 Alt(Windows/Linux)或 Option(macOS)点击可添加多个光标,同时编辑多处代码。 10. 远程开发支持 通过 Remote - SSH、Remote - Containers 等扩展,可直接连接远程服务器或开发容器,实现无缝协作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值