select死锁问题

本文探讨了两个事务分别对两条数据加S锁时产生的锁竞争现象,并深入分析了当select列未被索引完全覆盖时,对非聚集索引加S锁及聚集索引加X锁的具体情况。给出了在SELECT中使用WITH(NOLOCK)来缓解锁竞争的方法。

场景:
2个事务分别对2条数据加了S锁,然后都要更新对方的数据
1个事务做UPDATE操作,同时并发了一个非事务慢查询
场景1出现频率低,简单调整程序或业务规则可避免,在此不研究
场景2出现频率高,特别是存在大量慢查询的情况,以下给出原理及适用于SL的解决方案


原因分析:
这里写图片描述
当select列没有被索引完全覆盖时,先对非聚集索引加S锁,然后需要通过聚集索引找到其他列,这时要申请聚集索引的S锁
update操作会先对聚集索引加X锁,在更新非聚集索引列后要重排索引,则要申请这个非聚集索引的X锁


解决方案:
在SELECT 中加WITH(NOLOCK)

NOLOCK 可能把没有提交事务的数据也显示出来
READPAST 会把被锁住的行不显示出来(不考虑)

做好并发控制及状态验证

### 防止或解决 SQL 中 SELECT 语句引发的死锁问题 为了有效避免或解决由 `SELECT` 语句引起的死锁问题,可以从以下几个方面入手: #### 1. 减少共享锁持有时间 长时间持有的共享锁会增加与其他事务冲突的可能性。可以通过以下方式缩短锁定时间: - **立即提交事务**:在交互式命令行或其他环境中执行完必要的操作后应尽快提交事务[^1]。 - **避免不必要的延迟**:如果在 `SELECT ... FOR UPDATE` 或 `SELECT ... LOCK IN SHARE MODE` 后引入了人为延迟(如等待逻辑),可能会加剧死锁风险[^2]。 #### 2. 调整隔离级别 高隔离级别的事务更容易导致死锁现象发生。对于某些场景来说,适当降低隔离级别可能是一个有效的解决方案: - 如果应用程序能够容忍读取未提交的数据,则可以考虑将隔离级别降为 READ UNCOMMITTED; - 对于仅需短暂访问数据而不改变其状态的操作,尝试使用较低强度的锁模式来替代默认行为。 #### 3. 维持一致性访问路径 当多个表或多条记录需要在同一事务内被修改时,确保每次按照相同的顺序进行处理非常重要。这样可以显著减少跨资源竞争的机会从而预防潜在的循环依赖关系形成死锁条件。 #### 4. 创建合适索引 良好的索引设计不仅有助于提高查询效率,还可以间接帮助减少锁的数量和范围。具体而言: - 确保经常用于过滤条件列上有建立高效索引; - 使用覆盖索引来满足尽可能多的需求而无需回表检索原始数据页上的信息。 #### 5. 替代显式锁定策略 除非绝对必要,否则尽量避免直接指定带有锁定提示 (`WITH (ROWLOCK)` 等) 的查询语法。因为这些指令往往会强制施加更强硬类型的锁控制,反而增加了复杂性和错误概率。相反地,在大多数情况下依靠数据库引擎自动管理即可获得良好效果[^3]。 #### 示例代码展示如何优化 SELECT 查询以防止死锁 以下是几个实际例子展示了上述原则的应用方法: ```sql -- 方法一: 提交短小精悍的事物单元 BEGIN TRANSACTION; SELECT * FROM table_name WHERE id = @id FOR UPDATE; -- 执行其他相关业务逻辑... COMMIT; -- 方法二: 修改隔离级数至适合程度 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN TRANSACTION; SELECT column_list INTO temp_table FROM source_table WITH(NOLOCK); END TRANSACTION; -- 方法三: 设定固定扫描次序并利用索引加速查找过程 CREATE INDEX idx_column ON target_table(column); BEGIN TRANSACTION; INSERT INTO destination_table (columns...) SELECT columns... FROM intermediate_result_set irs JOIN another_table at USING common_key_field ORDER BY some_deterministic_criterion ASC; COMMIT; ``` 以上片段分别体现了快速完成事物、调整隔离等级以及构建辅助结构三种常见手段的实际运用情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值