update的where条件要把索引的字段带上,要不然就全表锁
update的where条件要把索引的字段带上,要不然就全表锁
文章目录
update的where条件要把索引的字段带上,要不然就全表锁
本文主要内容
背景
在学习中总结一下内容
关于锁的表
sql加锁思考点
InnoDB行锁实现方式
本文主要内容
报错了: java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction
对表进行更新和插入操作,在update的时候出现上述异常,经过排查发现是锁表的原因。
背景
建表语句如下:
表名为: app_pay_log_test
索引为:UNIQUE KEY rso_orderid_idx (rso,order_id)
CREATE TABLE `app_pay_log_test` (
`rso` varchar(50) NOT NULL DEFAULT '-1' COMMENT '充值渠道',
`order_id` varchar(100) NOT NULL COMMENT '订单id',
`amount` decimal(20,2) NOT NULL COMMENT '充值金额',
`product` varchar(50) DEFAULT NULL,
UNIQUE KEY `rso_orderid_idx` (`rso`,`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='手游充值订单';
1
2
3
4
5
6
7
出现异常的执行操作为:
UPDATE `app_pay_log_test` SET `product`=$2 WHERE `order_id`=$1 AND `product` is NULL
1
这里全表扫描锁表了,update的where条件把索引的字段要带上,要不然就全表锁。
也就是说要把检索条件上加上索引。而本表的索引是联合索引,上面的sql没有走索引,导致去全表扫描,出现表锁。
解决办法:
UPDATE `app_pay_log_test` SET `product`=$2 WHERE `rso`=$0 AND `order_id`=$1 AND `product` is NULL
1
实际上,不管是插入更新查询都需要走索引才不会那么容易出现全表扫描。
在学习中总结一下内容
InnoDB行锁是通过给索引上的索引项加锁来实现的。
InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。
关于锁的表
由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。
MySQL 5.5 中,information_schema库中新增了三个关于锁的表,即 innodb_trx、innodb_locks 和 innodb_lock_waits.
其中 innodb_trx 表记录当前运行的所有事务,innodb_locks 表记录当前出现的锁,innodb_lock_waits 表记录锁等待的对应关系。
具体用法可以参考:表结构说明
SELECT * FROM information_schema.INNODB_TRX\G;
SELECT * FROM information_schema.innodb_locks \G
SELECT * FROM information_schema.innodb_lock_waits \G
1
2
3
在 innodb_trx 表的第一行,trx_id为360F表示事务id,状态(trx_state)为等待状态,线程ID为2,事务用到的表为1(trx_tables_in_use),有1(trx_tables_locked)个表被锁。可以使用 kill trx_mysql_thread_id 杀死这个sql线程。
mysql> SELECT * FROM information_schema.innodb_trx \G
*************************** 1. row ***************************
trx_id: 360F
trx_state: LOCK WAIT
trx_mysql_thread_id: 2
trx_query: UPDATE user SET name="lock_waits" WHERE ID = 2
trx_tables_in_use: 1
trx_tables_locked: 1
1
2
3
4
5
6
7
8
sql加锁思考点
前提一:筛选列是不是主键?
前提二:当前系统的隔离级别是什么?(不同隔离级别 锁类型不同)
前提三:筛选列如果不是主键,那么筛选列上有索引吗?
前提四:筛选列上如果有二级索引,那么这个索引是唯一索引吗?(唯一索引只锁一行)
前提五:两个SQL的执行计划是什么?索引扫描?全表扫描?(走行锁还是表锁或者间隙锁)
InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁
在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。下面通过一些实际例子来加以说明。
(1)在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。
(2)由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。
(3)当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁。
(4)即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnoDB将使用表锁,而不是行锁。因此,在分析锁冲突时,别忘了检查SQL的执行计划,以确认是否真正使用了索引。
参考:
MySQL SHOW PROCESSLIST协助故障诊断 http://www.ywnds.com/?p=9337
记一次数据库死锁Deadlock https://www.jianshu.com/p/1c8fecb00563
MySQL 5.5 InnoDB 锁等待 https://dbarobin.com/2015/01/27/innodb-lock-wait-under-mysql-5.5/
————————————————
版权声明:本文为CSDN博主「Agly_Charlie」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Agly_Clarlie/article/details/83032289
update的where条件要把索引的字段带上,要不然就全表锁的更多相关文章
- 【从翻译mos文章】采用高速全扫描索引(index ffs) 为了避免全表扫描
采用高速全扫描索引(index ffs) 为了避免全表扫描 参考原始: Index Fast Full Scan Usage To Avoid Full Table Scans (Doc ID 701 ...
- update当根据条件不同时 更新同一个字段的方法 或多表插入
1.通过存储过程 循环 传值 create or replace procedure p_u isbegin for rs in (select distinct (rks) from rkbz)lo ...
- 陷阱~SQL全表扫描与聚集索引扫描
SqlServer中在查询时,我们为了优化性能,通常会为where条件的字段建立索引,如果条件比较固定还会建立组合索引,接下来,我们来看一下索引与查询的相关知识及相关陷阱. SQL表自动为主键加聚集索 ...
- 索引法则--LIKE以%开头会导致索引失效进而转向全表扫描(使用覆盖索引解决)
Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 DROP TABLE IF EXISTS staff; CREATE TABLE IF NOT EXISTS st ...
- mysql 全表扫描、全索引扫描、索引覆盖(覆盖索引)
full index scan:全索引扫描,查询时,遍历索引树来获取数据行.如果数据不是密集的会产生随机IO 在执行计划中是Type列,index full table scan:通过读物理表获取数据 ...
- MySQL中的全表扫描和索引树扫描
引言 在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况.在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type属性,ty ...
- SQL 语句调优 where 条件 数据类型 临时表 索引
基本原则 避免全表扫描 建立索引 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理 尽量避免大事务操作,提高系统并发能力 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方 ...
- 不恰当的update语句使用主键和索引导致mysql死锁
背景知识: 截至目前,MySQL一共向用户提供了包括DBD.HEAP.ISAM.MERGE.MyIAS.InnoDB以及Gemeni这7种Mysql表类型.其中DBD.InnoDB属于事务安全类表,而 ...
- mysql 通过测试'for update',深入了解行锁、表锁、索引
mysql 通过测试'for update',深入了解行锁.表锁.索引 条件 FOR UPDATE 仅适用于InnoDB存储引擎,且必须在事务区块(BEGIN/COMMIT)中才能生效. mysql默 ...
随机推荐
- SQL中group by的注意事项
最最最最重要的: group by有一个原则,就是select后面所有的列中,没有使用聚合函数的列,必须出现在group by子句中. group by子句中的注意事项: 1,不能使用别名(因为执行顺 ...
- workerman docker 运行试用
看到别人项目使用了workerman 作为webserver ,看了下介绍发现此框架还是挺强大的,比较喜欢使用 docker运行软件,所以基于php 7.3 的基础镜像简单使用下 环境准备 项目使用了 ...
- Attention篇(二)
主要是对<Attention is all you need>的分析 结合:http://www.cnblogs.com/robert-dlut/p/8638283.html 以及自己的 ...
- 第02组 Beta冲刺(4/4)
队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...
- 使用阿里云OSS上传文件
本文介绍如何利用Java API操作阿里云OSS对象存储. 1.控制台操作 首先介绍一下阿里云OSS对象存储的一些基本概念. 1.1 进入对象存储界面 登录阿里云账号,进入对象存储界面,如图所示. 进 ...
- 收藏一份devmem源码
/* * devmem2.c: Simple program to read/write from/to any location in memory. * * Copyright (C) 2000, ...
- HTML+css基础 p段落标签 a 超链接标签 Src和href有什么区别和关联? target属性 Meta标签
p段落标签: <p></p> 1.他是唯一一个可以不写结束标签的双标签. a 超链接标签: 从一个页面链接到另一个页面.靠的是href属性. Src和href有什么区别和关联 ...
- SQLServer查看分区表详细信息
SQL查看分区内记录个数,常规方法需要知道分区函数然后再显示,网上看到一个一句话显示的方法 ), ps.name ) as partition_scheme, p.partition_number, ...
- 在 ubuntu 下安装 mono 和 xsp4 ,并测试
1. 安装完 ubuntu 后,在 ubuntu 软件中查看是否自带了 mono 运行时和 XSP4,如果没有,则选中后,点击安装按钮. 2. 安装完后,在终端(类似于 Windows 上的命令行工具 ...
- mongodb 更新数据时int32变为double的解决办法
场景: 在命令手动的修改签到表的整型字段synState,multi参数是可以更新多条,如果是false则更新一条. db.getCollection("ClassRecordOneD ...