• MySQL死锁产生的原因和解决方法


    前言

    最近老顾经常碰到同事说,mysql又死锁了导致业务报错。今天我们就来聊聊死锁以及怎么解决

    锁类型

    mysql锁级别:页级、表级、行级

    表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

    行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

    死锁产生原因和示例

    1、产生原因:

    死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。

    死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

    那么对应的解决死锁问题的关键就是:让不同的session加锁有次序

    2、产生示例:

    案例一

    需求:将投资的钱拆成几份随机分配给借款人。

    起初业务程序思路是这样的:

    投资人投资后,将金额随机分为几份,然后随机从借款人表里面选几个,然后通过一条条select for update 去更新借款人表里面的余额等。

    例如两个用户同时投资,A用户金额随机分为2份,分给借款人1,2

    B用户金额随机分为2份,分给借款人2,1

    由于加锁的顺序不一样,死锁当然很快就出现了。

    对于这个问题的改进很简单,直接把所有分配到的借款人直接一次锁住就行了。

    Select * from xxx where id in (xx,xx,xx) for update

    在in里面的列表值mysql是会自动从小到大排序,加锁也是一条条从小到大加的锁

    第一个会话:

    注意:关闭掉自动提交set autocommit=0;

    1. mysql> select * from goods where goods_id in (2,3) for update;
    2. +----+--------+------+---------------------+
    3. | good_id | goods_name | price |
    4. +----+--------+------+---------------------+
    5. | 2 | bbbb | 1.00 |
    6. | 3 | vvv | 3.00 |
    7. +----+--------+------+---------------------+

    第二个会话:

    select * from goods where goods_id in (3,4,5) for update;

    锁等待中……

    案例二

    在开发中,经常会做这类的判断需求:根据字段值查询(有索引),如果不存在,则插入;否则更新。

    以id为主键为例,目前还没有id=22的行

    注意:关闭掉自动提交set autocommit=0;

    第一个会话:

    select * from goods where goods_id=22 for update;

    第二个会话:

    select * from goods where goods_id=23  for update;

    再在第一个会话:

    insert into goods values(22,'ac',11.5);

    锁等待中……

    再到第二个会话:

    insert into goods values(23,'bc',23.0);

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    当对存在的行进行锁的时候(主键),mysql就只有行锁。

    当对未存在的行进行锁的时候(即使条件为主键),mysql是会锁住一段范围

    锁住的范围为:

    (无穷小或小

  • 相关阅读:
    17. 异常处理
    机器学习 第11章 特征选择与稀疏学习
    C++入门学习2-指针与整型数组(Clion)
    服务器安装运行jupyter notebook
    [附源码]java毕业设计宿舍管理系统
    Spring6 的JdbcTemplate的JDBC模板类的详细使用说明
    [论文笔记]UNILM
    Java基础——面向对象(复习)
    OC-编译错误
    Linux安装Python3.10与部署flask项目实战详细记录
  • 原文地址:https://blog.csdn.net/java1527/article/details/127105144