首页 > 数据库 >举一个数据库死锁的例子,MySQL 怎么解决死锁?

举一个数据库死锁的例子,MySQL 怎么解决死锁?

时间:2023-05-03 18:58:57浏览次数:44  
标签:事务 版本号 数据库 用户 死锁 MySQL 数据

转载:https://juejin.cn/post/7072000882128191518

分析&回答
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
死锁的第一种情况
一个用户A 访问表A(锁住了表A),然后又访问表B;另一个用户B 访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。
解决方法:
这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理,必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。
死锁的第二种情况
用户A查询一条纪录,然后修改该条纪录;这时用户B修改该条纪录,这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A 有共享锁存在所以必须等A释放掉共享锁,而A由于B的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现了死锁。这种死锁比较隐蔽,但在稍大点的项目中经常发生。如在某项目中,页面上的按钮点击后,没有使按钮立刻失效,使得用户会多次快速点击同一按钮,这样同一段代码对数据库同一条记录进行多次操作,很容易就出现这种死锁的情况。
解决方法:

对于按钮等控件,点击后使其立刻失效,不让用户重复点击,避免对同时对同一条记录操作。
使用乐观锁进行控制。乐观锁大多是基于数据版本(Version)记录机制实现。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是 通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数 据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。乐观锁机制避免了长事务中的数据 库加锁开销(用户A和用户B操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系统整体性能表现。Hibernate 在其数据访问引擎中内置了乐观锁实现。需要注意的是,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户更新操作不受我们系统的控制,因此可能会造 成脏数据被更新到数据库中。
使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现,如Oracle的Select … for update语句,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。如一个金融系统, 当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户账户余额),如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读 出数据、开始修改直至提交修改结果的全过程,甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对成百上千个并发,这 样的情况将导致灾难性的后果。所以,采用悲观锁进行控制时一定要考虑清楚。

死锁的第三种情况
如果在事务中执行了一条不满足条件的update语句,则执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行后,就很容易产生死锁和阻塞。类似的情 况还有当表中的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描,最终应用系统会越来越慢,最终发生阻塞或死锁。
解决方法:
SQL语句中不要使用太复杂的关联多表的查询;使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句,建立相应的索引进行优化。
反思&扩展
总体上来说,产生内存溢出与锁表都是由于代码写的不好造成的,因此提高代码的质量是最根本的解决办法。有的人认为先把功能实现,有BUG时再在测试阶段进行修正,这种想法是错误的。正如一件产品的质量是在生产制造的过程中决定的,而不是质量检测时决定的,软件的质量在设计与编码阶段就已经决定了,测试只是对软件质量的一个验证,因为测试不可能找出软件中所有的BUG。

作者:刷刷面试
链接:https://juejin.cn/post/7072000882128191518
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:事务,版本号,数据库,用户,死锁,MySQL,数据
From: https://www.cnblogs.com/chenyi502/p/17369522.html

相关文章

  • mysql -- 事件
    MySQL的EVENTS是用来处理计划任务的。MySQL使用称为事件调度线程的特殊线程来执行所有预定事件。默认情况下,事件调度线程是未启用(版本低于8.0.3)的状态,如要启用它,可以执行以下命令:>SETGLOBALevent_scheduler=ON;>showvariableslike'%event_scheduler%';+-----------......
  • django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.3 or newer is requi
     1、在项目中__init__.py中这个报错原因,python3.5以上版本不支持这种方式frompymysqlimportinstall_as_MySQLdbinstall_as_MySQLdb()解决:importpymysqlpymysql.version_info=(1,4,3,"final",0)#指定了pymysql的版本:1.4.3,按照你版本修改pymysql.install_as_MySQLdb()......
  • java基于springboot+vue非前后端分离的影城管理系统、影院销售管理系统,附源码+文档+PP
    1、项目介绍本影城管理系统主要包括二大功能模块,即用户功能模块和管理员功能模块。(1)管理员模块:系统中的核心用户是管理员,管理员登录后,通过管理员功能来管理后台系统。主要功能有:首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订......
  • idea创建SpringBoot项目报错For artifact {mysql:mysql-connector-java:null:jar}: Th
    Forartifact{mysql:mysql-connector-java:null:jar}:Theversioncannotbeempty.报错如图:pom.xml文件如图:添加版本号:就好了......
  • 基于阿里云数据库TiDB的性能压测初体验
    作者:arron基于阿里云数据库TiDB的性能压测初体验申请阿里云TiDB地址:https://market.aliyun.com/isv-pingcap的过程,申请和部署过程非常简单直观,按提示一步步来即可,这里就忽略了。本次实验,主要对该云TiDB集群进行性能测试,使用测试工具有sysbench,tpcc,CH-benCHmark参考文档:如何用......
  • Win11系统,VS2022编写数据库程序,小体积,绿色单文件,支持密码保护,XP到Win11都能运行
    在WIN11中用VS2022编写小体积的绿色单文件,支持密码保护,XP到WIN11都能运行的数据库程序1.用VC60建立一个Win32工程,VC60建立的工程默认是字节型的。2.用VS2010读取并转换为2010格式,再用VS2022读取,选择SDK和平台都不升级3.把wxsqlite3-4.5.1.zip\wxsqlite3-4.5.1\sqlite3se......
  • harbor数据库迁移
    harbor数据库迁移(相同版本间迁移)一、数据导出(旧harbor机)1、进入数据库容器[root@localhost~]#dockerexec-uroot-itd53efe26b3da/bin/bash12、导出registry数据库**root[**/**]#**pg_dump-Upostgresregistry>registry.sql​**root[**/**]#**exit1233......
  • Java读取数据库表
    Java读取数据库表packagecom.easycrud.builder;importcom.easycrud.utils.PropertiesUtils;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.sql.*;/***@BelongsProject:EasyCrud*@BelongsPackage:com.easycrud.builder*@Author:xpx......
  • java基于springboot+vue前后端分离的超市进销存系统管理系统、超市管理系统,附源码+数
    1、项目介绍超市进销存系统,通过这个系统能够满足超市进销存系统的管理及员工的超市进销存管理功能。系统的主要功能包括:首页、个人中心、员工管理、客户管理、供应商管理、承运商管理、仓库信息管理、商品类别管理、商品信息管理、采购信息管理、入库信息管理、出库信息管理、销......
  • PHP: mysql 5.7 and php 5.6 导入记事本编号查询不了和中文乱码问题
    --https://dev.mysql.com/doc/refman/8.0/en/charset-database.htmlshowvariableslike"character_set_%";CREATEDATABASE`geovindu`CHARACTERSETutf8COLLATEutf8_general_ci;--mysql官方说明文档才知道原来MySQL8.0已经已经把默认字符集升级成ut8mb4了,和5.0有区......