Mysql | 数据库锁表的原因和解决方法

本文探讨了在并发环境下执行数据库更新操作时出现锁表现象的原因,并提供了具体的案例分析及解决办法。通过添加索引来避免表锁,提高数据库操作效率。

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

锁表的原因:
当多个连接(数据库连接)同时对一个表的数据进行更新操作,那么速度将会越来越慢,持续一段时间后将出现数据表被锁的现象,从而影响到其它的查询及更新。  
例如:
存储过程循环30次更新操作(cycore_file_id 为唯一标识)


/*30次更新操作*/ BEGIN   DECLARE v1 INT DEFAULT 30;   WHILE v1 > 0 DO
    update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
    SET v1 = v1 - 1;   END WHILE;

END

执行结果(速度非常慢)

时间: 29.876s

Procedure executed successfully
受影响的行: 0

200个数据更新操作,三个数据库连接同时执行

update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
 update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
 update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
 update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
 update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
 update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
...等等

执行结果(持续一段时间后速度越来越慢,出现等待锁)

# Time: 151208 22:41:24
# User@Host: zmduan[zmduan] @ [192.168.235.1] Id: 2
# Query_time: 1.848644 Lock_time: 0.780778 Rows_sent: 0 Rows_examined: 393382
SET timestamp=1449643284;
update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';

.........
........

# User@Host: zmduan[zmduan] @  [192.168.235.1]  Id:     2
# Query_time: 2.868598  Lock_time: 1.558542 Rows_sent: 0  Rows_examined: 393382
SET timestamp=1449643805;
update jx_attach set complete=1,attach_size=63100 where cycore_file_id='56677142da502cd8907eb58f';
[root@localhost log]# tail -f slow_query.log 
# User@Host: zmduan[zmduan] @  [192.168.235.1]  Id:    19
# Query_time: 1.356797  Lock_time: 0.000169 Rows_sent: 1  Rows_examined: 393383
SET timestamp=1449643805;

上述例子的原因分析:
MySQL的innodb存储引擎支持行级锁,innodb的行锁是通过给索引项加锁实现的,这就意味着只有通过索引条件检索数据时,innodb才使用行锁,否则使用表锁。根据当前的数据更新语句(update jx_attach set complete=1,attach_size=63100 where cycore_file_id=‘56677142da502cd8907eb58f’;),该条件字段cycore_file_id并没有添加索引,所以导致数据表被锁。
解决办法
为cycore_file_id添加索引
最终效果(30次更新操作)
时间: 0.094s
Procedure executed successfully
受影响的行: 0

上述引用出处:https://blog.csdn.net/yangaliang/article/details/79713530

另外又搜集一些在并发执行时会锁表的sql语句,如下:
这里写图片描述

解释以及说明(前提是并发执行):
假设kid是表table 的 一个索引字段 且值不唯一
1.如果kid 有多个值为12的记录那么:
update table set name=’feie’ where kid=12;
会锁表
2.如果kid有唯一的值为1的记录那么:
update table set name=’feie’ where kid=1;
不会锁

总结:用索引字段做为条件进行修改时, 是否表锁的取决于这个索引字段能否确定记录唯一,当索引值对应记录不唯一,会进行锁表,相反则行锁。


如果有两个delete 而 kid1 与 kid2是索引字段
语句1 delete from table where kid1=1 and kid2=2;
语句2 delete from table where kid1=1 and kid2=3;
这样的两个delete 是不会锁表的
语句1 delete from table where kid1=1 and kid2=2;
语句2 delete from table where kid1=1 ;
这样的两个delete 会锁表
总结:同一个表,如果进行删除操作时,尽量让删除条件统一,否则会相互影响造成锁表


引用出处:https://blog.csdn.net/truelove12358/article/details/53288049

### 解决MySQL数据库中的定问题 当遇到MySQL数据库中的定问题时,可以通过多种方法来诊断并解决问题。首先了解机制对于有效处理此类问题是至关重要的。 #### 1. 使用`SHOW OPEN TABLES`查看被定的 为了识别哪些处于定状态,可以执行以下命令: ```sql SHOW OPEN TABLES WHERE In_use > 0; ``` 这将显示所有正在使用的及其定情况[^1]。 #### 2. 查找造成死的具体会话 有时多个事务可能会相互等待对方释放资源而导致现象发生。此时可借助于`INFORMATION_SCHEMA.INNODB_LOCKS`视图以及相关联的`INFORMATION_SCHEMA.INNODB_TRX`视图来进行分析: ```sql SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_pid, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_pid, b.trx_query blocking_query FROM INFORMATION_SCHEMA.innodb_lock_waits w JOIN INFORMATION_SCHEMA.innodb_trx b ON b.trx_id = w.blocking_trx_id JOIN INFORMATION_SCHEMA.innodb_trx r ON r.trx_id = w.requesting_trx_id; ``` 上述查询语句能够帮助定位到具体的阻塞源[^2]。 #### 3. 终止长时间运行或者有问题的进程 一旦确认了引起问题的过程,则可以直接终止它们以解除定状况。使用`KILL QUERY`或`KILL CONNECTION`命令结束指定ID对应的活动: ```sql -- 杀掉某个特定连接上的查询 KILL QUERY thread_id; -- 或者完全断开该客户端连接 KILL CONNECTION connection_id; ``` 请注意,在采取此行动之前应谨慎评估影响范围,并确保不会丢失重要数据[^3]。 #### 4. 调整配置参数优化并发控制 长期来看,调整一些与定行为有关的服务器变量可能有助于预防未来再次出现类似的问题。例如设置更短的事物超时时间(`innodb_lock_wait_timeout`)、启用自动提交模式等措施都可以改善系统的响应速度稳定性。 #### 5. 定期维护计划 定期对数据库进行健康检查,包括但不限于清理不必要的索引、重组碎片化的格空间等工作也有助于维持良好的性能现,从而间接减少了因高负载引发的潜在争用风险。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值