单机事务中死锁产生的原因及解决办法

产生原因:

  • 两个线程
  • 不同方向
  • 相同资源

只要上面3个碰在一起一定会出现死锁问题!

举个例子:转账

两个事务单元
单机事务中死锁产生的原因及解决办法_第1张图片

事务单元一
第一步操作:Lock Bob
第二部操作:Lock Simth

事务单元二
第一步操作:Lock Simth
第二部操作:Lock Bob

他们俩都持有一把锁;
事务单元2想要Lock Bob的时候,他是进不到Bob那个锁上面的,于是事务单元2就等待了;
而事务单元1想要Lock Smith的时候,他也是进不到Smith的那个锁上面的,他也会在外面等待;
相互之间等待,而相互之间又维持了一个锁,这就是死锁产生的原因

死锁解决办法:

  • 尽可能不死锁
    如:尽可能降低隔离级别,因为死锁的核心主要就是事务之间相互等待产生的;
    不加读锁自然而然就能减少死锁的可能;
    这个一般对用户要求较高,所以一般数据库会提供两个主要的死锁检测的方法:第一种交碰撞检测;第二种叫等锁超时
  • 碰撞检测
    把事务单元和事务单元所维持的锁都记录下来,比如把事务单元1所有等待的锁,去申请锁之前先记录到内存里,当他锁住Bob的时候,再去锁住Smith的时候需要去申请另外一把锁,然后利用Smith在查看看这把锁申请的事务单元有哪些锁,发现事务单元2,然后去看事务单元2又是在申请哪些锁,会发现又回来了,于是在这种情况下,就认为在事务单元1中Lock Smith的时候发生了一个碰撞;于是解决了这个死锁问题,只要终止一边就可以了!
    这种方式的效率一般来说是最高的;等锁超时效率稍微会低一点
  • 等锁超时
    也是一种比较常见的作法,我等待持有锁的时间,比如持有超过一分钟,我就认为这个锁可能有问题,超时了直接给你报错,但这种方式会带来一个问题;比如超长事务,这种死锁检测的方式会导致每一个死锁被发现都需要非常长的时间,有些时候是不能接受的,所以在主流的数据库中主要是使用碰撞检测;

你可能感兴趣的:(MySQL,数据库)