MySQL死锁的产生原因以及解决方案_Mysql

来源:脚本之家  责任编辑:小易  

这个2113问题,问的就有问题,你对同一条记录,同时想5261将use设置成1或2,业4102务逻辑就有问题啊。我1653原来处理过类似的问题,介绍一下我的处理方式,在use表中,增加一个字段b,默认值是0,在事物一开始的时候,先将你要处理的那条记录的b值,设置成1,再事物全都处理完毕后,在将1更新成0。如果事物一开始发现这条记录的b值是1,则直接提示用户,正在对同一条数据进行处理,请稍后在试,代码里直接就return了,不往下进行。说白了,就是用一个字段,把一条记录锁住,事物一开始先判断锁没锁,如果锁了就提示用户,如果没锁,就锁住,然后向下进行,但是,无论是正常处理完,还是回滚,或者是抛出异常,都不要忘了把锁解开。更多追问追答追问判断具体怎么判断追答晕,怎么判断???select b from use where uid=1查出来的结果判断是0还是1追问select 查询是否被锁的 是不是后面还需要添加for update呢?www.zgxue.com防采集请勿采集本网。

数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并 发控制的一个非常重要的技术。在实际应用中经常会遇到的与锁相关的异常情况,当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就会出现死锁,严 重影响应用的正常执行。

MySQL死锁问题的相关知识是本文我们主要要介绍的内容,接下来我们就来一一介绍这部分内容,希望能够对您有所帮助。 1、MySQL常用存储引擎的锁机制 MyISAM和

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两 种基本的锁类型来对数据库的事务进行并发控制。

mysql死锁怎么解决  我来答 分享 微信扫一扫 新浪微博 QQ空间 举报 浏览8 次 可选中1个或多个下面的关键词,搜索相关资料。也可直接点“搜索资料”搜索

死锁的第一种情况

产生死锁的四个必要条件: (1) 互斥条件:一个资源每次只能被一个进程使用。 (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

一个用户A 访问表A(锁住了表A),然后又访问表B;另一个用户B 访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。

引起死锁的原因:互斥、占有且等待、非剥夺、循环等待 解决死锁的方法:预防死锁、避免死锁、检测并解除死锁

解决方法:

在老版本的MySQL 3.22中,MySQL的单表限大小为4GB,当时的MySQL的存储引擎还是ISAM存储引擎。但是,当出现MyISAM存储引擎之后,也就是从MySQL 3.23开始,

这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进 行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。

死锁的第二种情况

用户A查询一条纪录,然后修改该条纪录;这时用户B修改该条纪录,这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A 有共享锁存在所以必须等A释放掉共享锁,而A由于B的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现了死锁。这种死锁比较隐蔽,但在稍大点的项 目中经常发生。如在某项目中,页面上的按钮点击后,没有使按钮立刻失效,使得用户会多次快速点击同一按钮,这样同一段代码对数据库同一条记录进行多次操 作,很容易就出现这种死锁的情况。

解决方法:

在老版本的MySQL 3.22中,MySQL的单表限大小为4GB,当时的MySQL的存储引擎还是ISAM存储引擎。但是,当出现MyISAM存储引擎之后,也就是从MySQL 3.23开始,

1、对于按钮等控件,点击后使其立刻失效,不让用户重复点击,避免对同时对同一条记录操作。

2、使用乐观锁进行控制。乐观锁大多是基于数据版本(Version)记录机制实现。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是 通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数 据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。乐观锁机制避免了长事务中的数据 库加锁开销(用户A和用户B操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系统整体性能表现。Hibernate 在其数据访问引擎中内置了乐观锁实现。需要注意的是,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户更新操作不受我们系统的控制,因此可能会造 成脏数据被更新到数据库中。

3、使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现,如Oracle的Select … for update语句,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。如一个金融系统, 当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户账户余额),如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读 出数据、开始修改直至提交修改结果的全过程,甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对成百上千个并发,这 样的情况将导致灾难性的后果。所以,采用悲观锁进行控制时一定要考虑清楚。

死锁的第三种情况

如果在事务中执行了一条不满足条件的update语句,则执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行后,就很容易产生死锁和阻塞。类似的情 况还有当表中的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描,最终应用系统会越来越慢,最终发生阻塞或死锁。

解决方法:

在老版本的MySQL 3.22中,MySQL的单表限大小为4GB,当时的MySQL的存储引擎还是ISAM存储引擎。但是,当出现MyISAM存储引擎之后,也就是从MySQL 3.23开始,

SQL语句中不要使用太复杂的关联多表的查询;使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句,建立相应的索引进行优化。

小结

总体上来说,产生内存溢出与锁表都是由于代码写的不好造成的,因此提高代码的质量是最根本的解决办法。有的人认为先把功能实现,有BUG时再在测试阶段进 行修正,这种想法是错误的。正如一件产品的质量是在生产制造的过程中决定的,而不是质量检测时决定的,软件的质量在设计与编码阶段就已经决定了,测试只是 对软件质量的一个验证,因为测试不可能找出软件中所有的BUG。

以上就是MySQL死锁的产生原因以及解决方案的详细内容,更多关于MySQL死锁的资料请关注真格学网其它相关文章! 您可能感兴趣的文章:由不同的索引更新解决MySQL死锁套路Mysql使用kill命令解决死锁问题(杀死某条正在执行的sql语句)MySQL redo死锁问题排查及解决过程分析MySQL中由load data语句引起死锁的解决案例mysql 数据库死锁原因及解决办法MySQL死锁问题分析及解决方法实例详解一次Mysql死锁排查过程的全纪录

可直接在mysql命令行执2113行:show engine innodb status\G;查看造成死锁的sql语句,分5261析索引情况,然后优4102化sql然后show processlist;另外可以打开慢1653查询日志,linux下打开需在my.cnf的[mysqld]里面加上以下内容:,是不是2113报了error1213(40001):deadlockfoundwhentryingtogetlock;tryrestartingtransaction的错误?如果是的话,5261那么应该是有别的程序,也在更4102新这个表。你需要确定另外一个程序处理的顺1653序。然后想办法让你的同步程序,与那个程序,错开时间运行,加锁情况与死锁原因分析为方5261便大家复现4102,完整表结构和数据如下:CREATE TABLE `1653t3` (`c1` int(11) NOT NULL AUTO_INCREMENT,`c2` int(11) DEFAULT NULL,PRIMARY KEY (`c1`),UNIQUE KEY `c2` (`c2`)) ENGINE=InnoDBinsert into t3 values(1,1),(15,15),(20,20);在 session1 执行 commit 的瞬间,我们会看到 session2、session3 的其中一个报死锁。这个死锁是这样产生的:1. session1 执行 delete  会在唯一索引 c2 的 c2 = 15 这一记录上加 X lock(也就是在MySQL 内部观测到的:X Lock but not gap);2. session2 和 session3 在执行 insert 的时候,由于唯一约束检测发生唯一冲突,会加 S Next-Key Lock,即对 (1,15] 这个区间加锁包括间隙,并且被 seesion1 的 X Lock 阻塞,进入等待;3. session1 在执行 commit 后,会释放 X Lock,session2 和 session3 都获得 S Next-Key Lock;4. session2 和 session3 继续执行插入操作,这个时候 INSERT INTENTION LOCK(插入意向锁)出现了,并且由于插入意向锁会被 gap 锁阻塞,所以 session2 和 session3 互相等待,造成死锁。死锁日志如下: INSERT INTENTION LOCK在之前的死锁分析第四点,如果不分析插入意向锁,也是会造成死锁的,因为插入最终还是要对记录加 X Lock 的,session2 和 session3 还是会互相阻塞互相等待。但是插入意向锁是客观存在的,我们可以在官方手册中查到,不可忽略:Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.插入意向锁其实是一种特殊的 gap lock,但是它不会阻塞其他锁。假设存在值为 4 和 7 的索引记录,尝试插入值 5 和 6 的两个事务在获取插入行上的排它锁之前使用插入意向锁锁定间隙,即在(4,7)上加 gap lock,但是这两个事务不会互相冲突等待。当插入一条记录时,会去检查当前插入位置的下一条记录上是否存在锁对象,如果下一条记录上存在锁对象,就需要判断该锁对象是否锁住了 gap。如果 gap 被锁住了,则插入意向锁与之冲突,进入等待状态(插入意向锁之间并不互斥)。总结一下这把锁的属性:1. 它不会阻塞其他任何锁;2. 它本身仅会被 gap lock 阻塞。在学习 MySQL 过程中,一般只有在它被阻塞的时候才能观察到,所以这也是它常常被忽略的原因吧...GAP LOCK在此例中,另外一个重要的点就是 gap lock,通常情况下我们说到 gap lock 都只会联想到 REPEATABLE-READ 隔离级别利用其解决幻读。但实际上在 READ-COMMITTED 隔离级别,也会存在 gap lock ,只发生在:唯一约束检查到有唯一冲突的时候,会加 S Next-key Lock,即对记录以及与和上一条记录之间的间隙加共享锁。通过下面这个例子就能验证:这里 session1 插入数据遇到唯一冲突,虽然报错,但是对 (15,20] 加的 S Next-Key Lock 并不会马上释放,所以 session2 被阻塞。另外一种情况就是本文开始的例子,当 session2 插入遇到唯一冲突但是因为被 X Lock 阻塞,并不会立刻报错 “Duplicate key”,但是依然要等待获取 S Next-Key Lock 。有个困惑很久的疑问:出现唯一冲突需要加 S Next-Key Lock 是事实,但是加锁的意义是什么?还是说是通过 S Next-Key Lock 来实现的唯一约束检查,但是这样意味着在插入没有遇到唯一冲突的时候,这个锁会立刻释放,这不符合二阶段锁原则。这点希望能与大家一起讨论得到好的解释。如果是在 REPEATABLE-READ,除以上所说的唯一约束冲突外,gap lock 的存在是这样的:普通索引(非唯一索引)的S/X Lock,都带 gap 属性,会锁住记录以及前1条记录到后1条记录的左闭右开区间,比如有[4,6,8]记录,delete 6,则会锁住[4,8)整个区间。对于 gap lock,相信 DBA 们的心情是一样一样的,所以我的建议是:1. 在绝大部分的业务场景下,都可以把 MySQL 的隔离界别设置为 READ-COMMITTED;2. 在业务方便控制字段值唯一的情况下,尽量减少表中唯一索引的数量。锁冲突矩阵前面我们说的 GAP LOCK 其实是锁的属性,另外我们知道 InnoDB 常规锁模式有:S 和 X,即共享锁和排他锁。锁模式和锁属性是可以随意组合的,组合之后的冲突矩阵如下,这对我们分析死锁很有帮助内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • java的struts框架中append标签与generator标签的使用
  • mysql version can not be less than 4.1 出错解决办法
  • 详解ubuntu server下启动/停止/重启mysql数据库的三种方式
  • mysql出现提示错误10061的解决方法
  • mysql绿色版(zip解压版)的安装图文教程(mysql-5.6.22-win32.zip
  • 详解mysql权限和索引
  • navicat无法远程连接mysql的解决方法
  • 如何开启mysql中的严格模式
  • mysql5.5.28安装教程 超详细!
  • mysql 选择插入数据(包含不存在列)具体实现
  • mysql 死锁:如何解决mysql死锁
  • 怎么解决mysql 事务出现死锁的问题
  • mysql 发生死锁问题请求帮助
  • mysql什么情况下会出现死锁
  • 用sql语句,怎么解决mysql数据库死锁
  • mysql死锁怎么解决
  • 什么是mysql死锁
  • 试述死锁产生的原因和解决办法
  • 使用MySQL数据库,都有哪些情况易出现死锁的情况?
  • 为什么说 MySQL 的表锁不会产生死锁
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全mssqlmysqlmariadboracledb2mssql2008mssql2005sqlitepostgresqlmongodbredisaccess数据库文摘数据库其它首页由不同的索引更新解决mysql死锁套路mysql使用kill命令解决死锁问题(杀死某条正在执行的sql语句)mysql redo死锁问题排查及解决过程分析mysql中由load data语句引起死锁的解决案例mysql 数据库死锁原因及解决办法mysql死锁问题分析及解决方法实例详解一次mysql死锁排查过程的全纪录java的struts框架中append标签与generator标签的使用mysql version can not be less than 4.1 出错解决办法详解ubuntu server下启动/停止/重启mysql数据库的三种方式mysql出现提示错误10061的解决方法mysql绿色版(zip解压版)的安装图文教程(mysql-5.6.22-win32.zip详解mysql权限和索引navicat无法远程连接mysql的解决方法如何开启mysql中的严格模式mysql5.5.28安装教程 超详细!mysql 选择插入数据(包含不存在列)具体实现mysql安装图解 mysql图文安装教程can""""t connect to mysql servwindows下mysql5.6版本安装及配置mysql字符串截取函数substring的mysql创建用户与授权方法mysql提示:the server quit withmysql日期数据类型、时间类型使用mysql——修改root密码的4种方法mysql update语句的用法详解mysql之timestamp(时间戳)用法mysql慢查询之pt-query-digest分析慢查询在mysql字段中使用逗号分隔符的方法分享windows10下mysql 8.0.19 安装配置方法图mysql全文索引实现简单版搜索引擎实例代码mysql安装 navicat 出现1044/1045错误的解ubuntu下磁盘空间不足导致mysql无法启动的mysql密码正确却无法本地登录-1045关于mysql查询带单引号及插入带单引号字符mysql数据库高级查询和多表查询mysql中interactive_timeout和wait_timeo
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved