0

0

说一下 mysql 的行锁和表锁?

幻夢星雲

幻夢星雲

发布时间:2026-02-27 09:47:32

|

450人浏览过

|

来源于php中文网

原创

行锁和表锁是mysql并发控制的核心机制,innodb的行锁通过锁定特定行提升并发性能,适用于高并发oltp系统,支持事务、隔离性和崩溃恢复,但可能引发死锁且开销较大;而myisam的表锁锁定整表,实现简单、开销小,适合读多写少或批量处理场景,但并发写入性能差、不支持事务,易导致数据不一致。选择应基于业务需求:现代高并发系统优先选用行锁(innodb),而在只读、日志类或低并发场景可考虑表锁(myisam)。

说一下 mysql 的行锁和表锁?

MySQL 的行锁和表锁是其并发控制的核心机制。简单来说,表锁就是锁定整张表,同一时间只有一个会话能对表进行写操作,读操作也可能受限;而行锁则只锁定需要操作的特定行,允许其他会话同时访问表的其他行,显著提升了并发性能。

谈到MySQL的锁,这玩意儿真是数据库性能优化的一个永恒话题。它就像是数据库里维持秩序的交警,决定了数据访问的先后顺序和并发程度。我个人在处理高并发系统时,最常打交道的还是行锁,尤其是InnoDB引擎下的行锁。

表锁,顾名思义,就是把整张表给锁住了。想想看,当你对一张表执行LOCK TABLES或者在MyISAM引擎下进行任何写入操作时,整个表就成了“禁区”。其他会话想写?排队去吧。想读?有时候也得等。这种简单粗暴的锁定方式,实现起来最容易,开销也最小,因为数据库不用费劲去判断具体锁定了哪一行,直接把门一关就行。所以,在某些读多写少、且对并发要求不高的场景,或者干脆就是数据仓库那种批处理任务里,MyISAM的表锁表现还行。但一旦涉及到频繁的并发写入,那简直就是灾难,吞吐量会直线下降。

行锁就精细多了,它只锁定你正在操作的那几行数据。比如,你更新了用户ID为100的记录,那么只有ID为100的那一行被锁住,其他用户仍然可以自由地更新用户ID为200的记录。这种粒度更细的锁定,显然能带来更高的并发性能。InnoDB就是行锁的忠实拥趸。它通过索引来锁定行,如果你操作的SQL语句没有用到索引,或者索引失效了,InnoDB可能会悄悄地把锁升级成表锁,或者锁住整个索引范围,这可就麻烦了,直接影响到并发。我遇到过不少性能问题,最后追查下来,都是因为SQL语句没用对索引,导致行锁变成了“伪表锁”。

这两种锁机制,没有绝对的好坏,只有适用不适用。在设计数据库时,你得根据业务场景来权衡。

MySQL 行锁和表锁:性能与并发的权衡,我该如何选择?

选择行锁还是表锁,或者说选择InnoDB还是MyISAM,这就像在选择高速公路和乡间小道。高速公路(行锁)虽然维护成本高,管理复杂,但能承载巨大的车流量(高并发);乡间小道(表锁)简单易行,但一旦车多起来就容易堵死。

从我的经验来看,绝大多数现代OLTP(在线事务处理)系统,即那些需要处理大量并发读写请求的业务,都应该毫无疑问地选择行锁,也就是InnoDB存储引擎。它的优势在于:

  • 高并发性: 允许多个事务同时操作不同的行,大大提升了系统的吞吐量。
  • 更好的隔离性: InnoDB支持更高级别的事务隔离,比如可重复读(Repeatable Read),能够有效避免脏读、不可重复读和幻读等问题。
  • 崩溃恢复能力: InnoDB使用事务日志(redo log和undo log)来保证数据的一致性和可恢复性,即使数据库崩溃也能恢复到一致状态。

但行锁也不是没有代价。它的开销比表锁大,因为数据库需要维护更多的锁信息,并进行更复杂的锁调度。另外,行锁也更容易引发死锁。

表锁(MyISAM)则适用于以下场景:

  • 读多写少,且并发写操作极少: 如果你的应用主要是查询,偶尔有写入,那么MyISAM的简单性可能带来略微的性能优势(在某些特定查询场景下,比如全表扫描)。
  • 数据仓库或报表类应用: 这些应用通常是批量导入数据,然后进行大量查询,对并发写入要求不高。
  • 非事务性操作: MyISAM不支持事务,如果你不需要事务特性,它可能更轻量。

但在实际项目中,我几乎已经不再主动选择MyISAM作为主存储引擎了。InnoDB的通用性和鲁棒性,让它成为了事实上的标准。

芝麻乐开源众筹cms系统
芝麻乐开源众筹cms系统

芝麻乐开源众筹系统采用php+mysql开发,基于MVC开发,适用于各类互联网金融公司使用,程序具备模板分离技术,您可以根据您的需要进行应用扩展来达到更加强大功能。前端使用pintuer、jquery、layer等....系统易于使用和扩展简单的安装和升级向导多重业务逻辑判断,预防出现bug后台图表数据方式,一目了然后台包含但不限于以下功能:用户认证角色管理节点管理管理员管理上传配置支付配置短信平

下载

深入理解InnoDB行锁机制:避免死锁和提升事务效率的秘诀

InnoDB的行锁机制,远比“只锁一行”听起来复杂。它内部通过各种类型的锁(共享锁S、排他锁X、意向共享锁IS、意向排他锁IX等)以及锁粒度(行锁、间隙锁、Next-Key Lock)来精细控制并发。

我印象最深的就是Next-Key Lock。它不仅锁住你操作的行,还会锁住该行所在的索引范围(间隙),这能有效防止幻读。比如,你执行SELECT * FROM users WHERE id > 100 FOR UPDATE;,InnoDB不仅会锁住所有ID大于100的现有行,还会锁住这些行之间的“空隙”,防止有新的ID插入到这个范围内。这对于保持数据一致性至关重要,但也可能意外地锁住比你预期更多的行,从而降低并发。

避免死锁: 死锁是行锁环境下最让人头疼的问题之一。当两个或多个事务互相等待对方释放锁时,就会发生死锁。InnoDB有死锁检测机制,一旦发现死锁,它会选择一个事务作为“牺牲品”并回滚它,以解除死锁。虽然数据库会自动处理,但我们作为开发者,应该尽量从代码层面避免它。

  • 固定加锁顺序: 比如,总是先更新A表再更新B表,而不是有些事务先A后B,有些事务先B后A。
  • 缩短事务时间: 事务越短,持有锁的时间就越短,发生冲突的概率就越低。
  • 减少锁范围: 确保SQL语句使用了正确的索引,避免行锁升级为表锁或锁住不必要的间隙。EXPLAIN是你的好朋友。
  • 使用FOR UPDATE时要谨慎: 它会给查询到的行加上排他锁,如果查询范围过大,或者索引不当,很容易造成锁竞争。

提升事务效率:

  • 批量操作: 尽量将多个小事务合并成一个大事务,减少事务开销。但要注意事务不要过大,否则会增加死锁风险和回滚成本。
  • 合理设计索引: 这是根本。没有合适的索引,行锁就形同虚设。
  • 优化SQL语句: 避免全表扫描,减少不必要的锁等待。
  • 设置合适的隔离级别: 默认的Repeatable Read已经很强大,但在某些场景下,如果业务允许,Read Committed可以提供更高的并发(因为它不会有间隙锁)。但这需要你对业务和数据一致性有深刻理解。

MyISAM表锁的局限性与应用场景:为什么它在OLTP中逐渐失宠?

MyISAM引擎在MySQL早期版本中是默认的存储引擎,但随着互联网业务对高并发、高可用和数据一致性要求的提高,它逐渐被InnoDB取代,尤其是在OLTP领域。

它失宠的原因很简单,就是并发性差。当一个写入操作(INSERT, UPDATE, DELETE)发生时,MyISAM会对整张表加写锁。这意味着,即使是简单的SELECT查询,也可能需要等待写锁释放。试想一下,一个高并发的电商网站,用户下单、支付、库存扣减,这些操作如果都用表锁,那系统基本就瘫痪了。

另外,MyISAM不支持事务。这意味着它无法保证操作的原子性、一致性、隔离性和持久性(ACID)。如果一个操作链中途失败,已经执行的部分无法回滚,可能导致数据不一致。这对于金融、交易等对数据一致性要求极高的业务来说,是不可接受的。

崩溃恢复能力差也是一个大问题。MyISAM没有事务日志,如果数据库在写入过程中崩溃,数据文件可能会损坏,导致数据丢失或不一致。我见过一些老系统,因为MyISAM崩溃导致数据恢复困难,甚至需要人工介入修复。

尽管如此,MyISAM也并非一无是处,它在某些特定场景下仍有其价值:

  • 日志记录表: 比如网站的访问日志、操作日志等,这些数据通常是追加写入,且不涉及更新或删除,对事务和高并发写入要求不高。MyISAM的简单性和较低的存储开销可能是一个选择。
  • 只读或读多写少的静态数据表: 例如一些配置表、字典表,一旦写入后很少更新,MyISAM的查询性能可能表现不错。
  • 全文索引: MyISAM提供了内置的全文索引功能,在MySQL 5.6之前,InnoDB没有这个功能(现在有了)。对于需要全文搜索的场景,MyISAM曾是一个不错的选择。
  • 数据量较小、对并发写入和事务要求不高的简单应用。

但总的来说,对于大多数需要处理并发事务的现代Web应用,InnoDB是更稳妥、更强大的选择。MyISAM更多地是作为一种历史遗留或特定工具的存在,而非通用解决方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1048

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

339

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

379

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1905

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

379

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1458

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

585

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

437

2024.04.29

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

0

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.4万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 838人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号