mysql 高并发update导致死锁的 情况

死锁产生的条件:
出现循环等待资源。

update对锁的流程:
       当sql发出一个update请求之后,数据库会对表中的每条记录加上U锁。然后数据库会根据where条件,将符合条件的记录转换为X锁。对不满足条件的记录释放U锁。

环境模拟
1. 创建数据库环境

--创建数据库
  create database DeadLockTest;
--创建数据表 (没有主键)
  use DealLocktest;
  create table t_table(
    A varchar(10),
    B varchar(10),
    C varchar(10)
  )
insert into  t_table values('a1','b1','c1');
insert into  t_table values('a2','b2','c2');
insert into  t_table values('a3','b3','c3');
insert into  t_table values('a4','b4','c4');
insert into  t_table values('a5','b5','c5');
insert into  t_table values('a6','b6','c6');
insert into  t_table values('a7','b7','c7');
insert into  t_table values('a8','b8','c8');
insert into  t_table values('a9','b9','c9');

创建完后,应该是这个样子:


2.准备高并发的查询环境

因为一个人测试,很不好模拟现场的环境。所以使用sql 的waitfor 阻塞某一个查询:
A要执行的sql语句:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
 begin tran
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
       update t_table
     set A='a2'
     where B='b2'
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
    EXEC sp_lock @@spid

   waitfor  delay '00:00:05'

   update t_table
     set A='b4'
     where B='b4'
     EXEC sp_lock @@spid
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
 commit tran

B要进行的sql语句

SET TRANSACTION ISOLATION LEVEL Read UNCOMMITTED
    begin tran
  update t_table
    set A='a1'
    where B='b1'
    EXEC sp_lock @@spid
   commit tran

因为A中第一条查询和第二天查询有5s间隔,所以整个的执行过程为:
1、执行A的第一条语句 阻塞5s
2、执行B的查询
3、A的阻塞释放,要执行A的第二条语句

要执行的图解:


分析:
1、执行A的查询的时候,数据库将所有的记录加上U锁,然后将将不是c2的记录全部释放U锁。对满足条件的数据添加X锁。此时,A事务还没有结束,A不会释放此时的X锁。
2、B查询的时候,B会对表中的所有记录添加U锁,因为B查询要用到t_table这张表,B查询c1的时候,满足条件给c1添加上X锁。执行c=2的时候,要给c2加U锁,此时该记录被A添加了X锁。所以B查询需要等A释放的X锁,才可以执行。此时B等待。B要等待A释放c2的X锁
3、A的阻塞释放之后,A要进行第二条查询。这个时候A要对符合第二个查询条件的记录添加X锁。当执行c1的时候,c1刚才被B添加了X锁。所以此时A等待。A在等待B的U锁释放。
结论
A在等待B释放X锁,B在等待A释放X锁。所以才会发生死锁。


解决方案:

       给查询条件加索引,原因参考下一篇详解索引。

总结
       死锁的发生,肯定是因为资源的循环等待。分析死锁,就是分析这些进程分别需要等待什么资源。在sql server中 一般可以使用 sql profiler进行死锁的监控。
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL高并发情况下有一些需要注意的地方。 首先,高并发情况下会有大量的并发请求同时向MySQL发送update操作。为了保证数据的正确性和一致性,可以采取以下措施: 1. 使用正确的索引:在高并发环境下,索引的选择非常重要。合适的索引可以加快查询速度,减少定的数据行数量。通过分析查询语句,优化表结构,选择合适的索引,可以有效减少的数量,提高并发性能。 2. 限制事务的范围:事务的范围越大,定的资源也越多,容易造成死锁和性能问题。因此,在高并发情况下,可以尽量使用短事务,减少事务处理的时间和影响范围。 3. 合理使用策略:MySQL提供了多种策略,如共享、独占、行、表等。在高并发情况下,可以根据具体需求,选择合适的策略。例如,使用行可以减少冲突,提高并发性能。 4. 使用事务隔离级别:MySQL支持不同的事务隔离级别,如读未提交、读已提交、可重复读和串行化。根据业务需求,选择合适的隔离级别。较高的隔离级别可以增加并发冲突的可能性,但能保证数据的完整性。 5. 合理配置MySQL参数:对于高并发情况,可以适当调整MySQL的参数。如增加最大连接数、增加缓冲区大小、调整线程数等,以提高并发处理能力。 除了以上几点,还可以考虑使用分库分表、缓存技术、读写分离等策略来解决高并发问题,从而提高系统的性能和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值