背景知识:

截至目前,MySQL一共向用户提供了包括DBD、HEAP、ISAM、MERGE、MyIAS、InnoDB以及Gemeni这7种Mysql表类型。其中DBD、InnoDB属于事务安全类表,而其他属于事务非安全类表。

DBD
    Berkeley DB(DBD)表是支持事务处理的表,由Sleepycat软件公司开发。它提供MySQL用户期待已久的功能--事务控制。事务控制在任何数据库系统中都是一个极有价值的功能,因为它们确保一组命令能成功地执行或回滚。

MyIASM

MyIASM基于了IASM代码,应该可以说是IASM的衍生品,不过增加了不少有用的扩展。它是MySQL的默认数据表类型,基于了传统的ISAM类型,ISAM是Indexed Sequential Access Method(有索引的顺序访问方法)的缩写,一般来说,它是存储记录和文件的标准方法。与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具。ISAM表格可以被压缩,而且它们支持全文搜索,不过它们是事务不安全的,而且也不支持外键。如果事务回滚将会造成不完全回滚,从而不具备原子性。所以假如忽略事务以及访问并发性的话,并且需要执行大量的SELECT检索语句的话,MyISAM将是最好的选择。

InnoDB

InnoDB是MySQL 4.0之后推出的一种比较新的数据表类型,这种类型是事务安全的。它与BDB类型具有相同的特性,它们还支持外键。InnoDB表格速度很快具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它。如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,同样应该使用InnoDB表。对于支持事务的InnoDB类型的表来说,影响速度的主要原因是AUTOCOMMIT默认设置是打开的,而且程序没有显式调用BEGIN 开始事务,导致每插入一条都自动提交,严重影响了速度。可以在执行sql前调用begin,多条sql形成一个事物(即使autocommit打开也可以),将大大提高性能。

MySQL的数据表类型很多,其中比较重要的是MyISAM,InnoDB这两种。

同时,MySQL有三种锁的级别:页级、表级、行级。

MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

MySQL这3种锁的特性可大致归纳如下:

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。

问题现象:

首先是数据库表结构如下:


 

 在执行

UPDATE ccvzb_room SET STATUS=1 WHERE begin_time<'2017-02-05 17:24:12'

报错,报错信息为:

ERROR 1062 (23000): Duplicate entry '000e2619f0c5487880829e4165e714ff-0' for key 'PRIMARY'

其实这条sql执行时,就产生了死锁,根据背景知识里的红色描述:如果用到了主键索引,mysql会锁定主键索引,如果用到了非主键索引,msyql会先锁定非主键索引,再锁定主键索引。如果两条sql执行间隔时间非常短的话就会出现资源争夺的情况,从而造成死锁。

解决办法:

解决办法一:

首先通过条件查询出符合条件的记录,然后根据查询出的结果的主键id再进行update操作。

UPDATE ccvzb_room a INNER JOIN ccvzb_room b ON a.room_id=b.room_id SET a.status=1 WHERE a.begin_time<'2017-02-05 17:24:12' AND a.status=0</span> 

解决办法二:

UPDATE ccvzb_room SET STATUS=STATUS+1 WHERE begin_time<'2017-02-05 17:24:12' AND STATUS=0 ORDER BY STATUS

经验总结:

电商无论前台后台的程序,都不应该存在仅根据非主键的几个字段一查就要update/delete的场景。即使有,也应该改为先把要更新的记录查出来然后逐条按主键id更新。

不恰当的update语句使用主键和索引导致mysql死锁的更多相关文章

  1. mysql-不恰当的update语句使用主键和索引导致mysql死锁

    背景知识:MySQL有三种锁的级别:页级.表级.行级. MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking):BDB存储引擎采用的是页面锁(page-level ...

  2. SQL语句新建表,同时添加主键、索引、约束

    SQL语句新建数据表   主键,索引,约束 CREATE TABLE [dbo].[T_SendInsideMessageRec]( [SendInsideMID] [uniqueidentifier ...

  3. Mybatis笔记 – insert语句中主键的返回

    在DBMS中可以使用insert语句显示指定自增主键值,但Mybatis中不可,即使指定了也无效,可以使用特殊的方式返回主键. 一.自增主键返回         mysql自增主键执行insert提交 ...

  4. Oracle基础维护02-表、主键、索引、表结构维护手册

    目录 一.项目新建表.主键.索引注意事项 二.举例说明建表.主建.索引的操作方法 2.1 设定需求如下 2.1.1 查询数据库有哪些表空间 2.1.2 本文档假设数据库有这两个业务用户的表空间 2.2 ...

  5. 【转载】mysql主键的缺少导致备库hang

    最近线上频繁的出现slave延时的情况,经排查发现为用户在删除数据的时候,由于表主键的主键的缺少,同时删除条件没有索引,或或者删除的条件过滤性极差,导致slave出现hang住,严重的影响了生产环境的 ...

  6. mysql主键的缺少导致备库hang

    最近线上频繁的出现slave延时的情况,经排查发现为用户在删除数据的时候,由于表主键的主键的缺少,同时删除条件没有索引,或或者删除的条件过滤性极差,导致slave出现hang住,严重的影响了生产环境的 ...

  7. 删除表空间的时候遇到的问题:ORA-02429: 无法删除用于强制唯一/主键的索引

    今天打算删除orcale数据库中无用的表空间,发现报错,查资料删除,写个过程留着备用.1.drop tablespace dldata INCLUDING CONTENTS CASCADE CONST ...

  8. ora-02429:无法删除用于强制唯一/主键的索引

    今天打算删除orcale数据库中无用的表空间,发现报错,查资料删除,写个过程留着备用. 1.drop tablespace dldata INCLUDING CONTENTS CASCADE CONS ...

  9. Oracle 添加主键和索引

    数据的主键和索引一般情况下都是必须的,特别是表有大量数据的时候,索引和主键更是必不可少,这样可以提供数据的查询效率: 一.创建表的同时创建主键约束 (1)无命名 create table studen ...

随机推荐

  1. DataTable distinct 去重复

    有时我们需要从DataTable中抽取Distinct数据,以前总是以对DataTable进行foreach之类纯手工方式获取. 近来发现DataView可以帮我们直接获取Distinct数据,汗一个 ...

  2. UVa 10716 - Evil Straw Warts Live

    题目大意:给一个字符串,判断是否能通过交换字母构成回文,如果能,计算所需的最小交换次数. 如果字符串中出现奇数次的字母的个数>1,则不能构成回文.然后...就没思路了...看网上说用贪心的思想先 ...

  3. UVa 10137 & ZOJ 1874 The Trip

    题目大意:n个学生去旅行,旅行中每个学生先垫付,最后平摊所有费用,多退少补,并且支出差距控制在1分钱以内,求最小的交易金额. @2013-8-16 以前在zoj做过,把原来的代码直接提交了,虽然AC了 ...

  4. SQL四种语言

    1.DDL(Data Definition Language)数据库定义语言statements are used to define the database structure or schema ...

  5. sklearn数据预处理-scale

    对数据按列属性进行scale处理后,每列的数据均值变成0,标准差变为1.可通过下面的例子加深理解: from sklearn import preprocessing import numpy as ...

  6. mysql 子查询优化

    今天用到要查询七天内都没有装机的门店信息,首先想到了用not in,先把装机的userid查出来,然后再id not in,但是这样就必须使用子查询,数据量少还可以,数据量大了的话,肯定效率特别低,因 ...

  7. U盘为什么还有剩余空间,但却提示说空间不够

    你的U盘是FAT32格式,它只支持单一小于4G的文件复制,将U盘改为NTFS格式,可以解决题.方法:开始——运行,输入“cmd”,回车,在命令符后输入:convert h: /fs:ntfs,回车(假 ...

  8. Cocos2d-x 多分辨率支持

    最近遇到多分辨率支持问题,所以查了一些资料.将一些收获共享一下,以便自己和其他需要的朋友日后参考. 如果我要建立一个cocos2d-x项目,我的目标是支持iphone3G( 480, 320 ),ip ...

  9. libcurl模拟登录CSDN并自动评论资源以获取积分

    软件及源码下载:(http://pan.baidu.com/s/1jGE52pK) 涉及到的知识点: C++多线程编程 libcurl的使用(包括发送http请求.发送cookie给服务器.保存coo ...

  10. LeetCode Database题解

    175. Combine Two Tables 使用外连接即可. # Write your MySQL query statement below select FirstName, LastName ...