SQL锁机制

根据锁的粒度,SQL锁主要分为表级锁、行级锁和页级锁。表级锁,顾名思义,直接锁住整张表。当某个会话对表进行写操作时,会先获得写锁,此时其他会话的所有操作都会被阻塞,直到锁被释放。这种锁开销小、加锁快,但并发能力较差,在MyISAM存储引擎中比较常见。行级锁则精细得多,它只锁定需要操作的那些数据行,其他行仍然可以正常访问。这在并发写操作频繁的场景下优势明显,但管理开销较大。InnoDB存储引擎支持行级锁,这也是它比MyISAM更适合高并发环境的重要原因。页级锁算是折中方案,锁定数据页(通常为4KB或8KB),粒度介于表锁和行锁之间。

从锁的模式来看,可以分为共享锁(S锁)和排他锁(X锁)。共享锁允许多个会话同时读取同一资源,但任何会话都不能修改------简单说就是"能读不能写"。排他锁则霸道得多,一个会话对资源加了排他锁后,其他会话既不能读也不能写,必须等待锁释放。这两种锁的兼容关系很简单:共享锁之间可以共存,但共享锁与排他锁、排他锁与排他锁之间互斥。

除了基本锁类型,还有意向锁这种机制。意向共享锁(IS)和意向排他锁(IX)是表级锁,它们的主要作用是"声明意图"。比如某个会话要对某些行加排他锁前,会先在表级别加一个意向排他锁。这样当另一个会话想要给整张表加锁时,通过检查意向锁就能快速知道表中是否有行被锁定,而不需要逐行检查,大大提升了效率。

说到锁就不得不提数据库的隔离级别。读未提交(Read Uncommitted)基本不加锁,可能读到别人未提交的数据;读已提交(Read Committed)通过加锁避免脏读,但可能出现不可重复读;可重复读(Repeatable Read)通过间隙锁等机制防止幻读;串行化(Serializable)则对所有读取都加锁,完全保证隔离性。以MySQL的InnoDB为例,在可重复读级别下,不仅会对现有数据行加锁,还会通过间隙锁锁定不存在的键值范围,有效防止其他事务在范围内插入新数据。

更新锁(U锁)是SQL Server中的特殊锁类型,它在更新操作初期使用。当需要先查找再更新时,更新锁可以防止多个会话同时查询数据后都试图更新,从而避免死锁。在找到需要更新的数据后,更新锁会升级为排他锁。

实际开发中,死锁是令人头疼的问题。两个会话各自持有对方需要的锁,又都在等待对方释放,形成无限等待。比如事务A先锁定了表T1,请求T2;同时事务B锁定了表T2,请求T1------典型的死锁场景。数据库通常有死锁检测和解除机制,会选择一个事务作为"牺牲者"回滚,让另一个继续执行。

合理使用锁需要结合业务场景。在查询语句中,可以通过SELECT ... FOR UPDATE对读取的行加排他锁,防止其他会话修改;或者使用SELECT ... LOCK IN SHARE MODE加共享锁。设置锁等待超时时间也是常用技巧,避免长时间阻塞。另外,尽量让事务简短,按相同顺序访问表资源,都能有效减少锁冲突。

锁机制是数据库并发控制的基石,理解不同锁的特性和适用场景,对设计高并发、高可用的系统至关重要。作为开发者,我们需要在数据安全性和系统性能间找到平衡点,让锁成为保障数据安全的利器,而不是系统性能的瓶颈。

相关推荐
AI你一生一世3 小时前
不止于时序存储:DolphinDB 如何成为 AI 时代的工业智能底座
java·人工智能·struts·时序数据库·工业智能·dolphindb·ai基础设施
云-缩影3 小时前
拆解 AI 图像生成应用的后端架构:ECS、OSS 和大模型 API 怎么配合
java·spring boot·后端
ss2734 小时前
为什么PostgreSQL适合AI场景?
数据库·人工智能·postgresql
瑞克-桑切斯4 小时前
7、MySQL 慢查询排查与优化实战指南
java·服务器·数据库
z06.5 小时前
MySQL索引
数据库·mysql
考虑考虑5 小时前
Posrgresql恢复.backup文件
数据库·后端·postgresql
云祺vinchin5 小时前
中小企业备份软件选型从恢复需求到总体成本评估
数据库·数据备份·中小企业备份·容灾备份软件
Zenova EdgeOS5 小时前
Go 工业边缘错误处理实战:用 errors 构建可追溯错误链
开发语言·数据库·golang
KKKlucifer5 小时前
国内数据安全服务的产品智能化转型:大模型赋能下的技术能力重构分析
大数据·数据库·重构
字节跳动开源6 小时前
OpenViking 上线原生 3D 内容理解模型
数据库·开源