您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

mysql锁-从实战中理解

时间:2023-01-03 11:34:48  来源:今日头条  作者:打篮球的程序员

MySQL锁可能是数据库知识篇幅中普遍比较难理解的一个知识点!以前对锁理解的也是停留在八股文的的阶段,经历了这次生产问题之后重新学习了

问题表现:

早上刚到公司还没进入状态,就被拉进一个群(dba找上门了)说数据库有大量锁等待异常。

代码中的sql: delete from
order_point_line_statistics where ep_id = 376330219 and created_at <= '2022-12-15 00:00:00'

Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ### The error may exist in class path resource [MyBatis/mApper/ext/OrderPointLineStatisticsExtMapper.xml]

The error occurred while setting parameters ### SQL: delete from order_point_line_statistics where ep_id = ? and created_at <= ? ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

事故现场

场景是在并发消费kafka数据的时候,起了一个事务,事务里先插入今天的数据,然后删除数据;

CREATE TABLE `ep` (

`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

`ep_id` int(11) NOT NULL COMMENT '企业ID',

`name` varchar(255) NOT NULL COMMENT '名称',

`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',

PRIMARY KEY (`id`),

KEY `idx_ep_id` (`ep_id`) USING BTREE,

KEY `idx_create_at` (`create_at`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

 

Session1

Session2

Locks

begin;

begin;

 

insert into ep(e_id, name, create_at) values(100, 'stt', '2022-12-04 00:00:00');

 

 

 

insert into ep(e_id, name, create_at) values(100, 'ssd', '2022-12-04 00:00:00');

 

select * from epG;
id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13
id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13
id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13
id: 4
e_id: 100
name: stt
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:41:47

select * from epG;
id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13
id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13
id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13
id: 5
e_id: 100
name: ssd
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:44:46

 

delete from ep where e_id=100 and create_at <= '2022-12-03 00:00:00';

 

lock wAIting&dead lock

这里粘贴一张复现的图:

 

事故还原

初始化记录

 

两个session分别执行一条插入后查看的锁记录:

 

session1执行delete语句的锁记录:

 


 

此时session2的锁记录:

 

可以明显的看出:

 

 

表中最大的记录id是6,事务中插入的记录id是15,session1锁住的记录id最大到10,其实当我存量数据id是连续的时候,session1会把我刚插入的id也会锁住,这也是我一直不理解的地方。

google中提了一个问题:
https://stackoverflow.com/questions/74972932/why-does-innodb-lock-more-records-when-range-deletion;大致回答的意思就是说:其实不管大范围还是小范围都一样 在根据ep_id和create_at筛选删除时,如果大范围时,会先挑ep_id=100先筛选 而且是边筛选边变锁,把筛到的结果就要锁住 ep_id=100的筛选结果包含session2的插入的数据 就锁等待了。

思考:

一:当我把delete语句中的时间范围缩小时,还是会锁住刚插入的记录吗?

答案是不会的,只会锁住符合条件的记录。 我想这也是符合预期的锁记录。

二:思考

1)、把插入语句和删除语句调换位置

在事务中先执行删除,虽然说session2也会产生锁等待,但是session1同样可以提交不会报错

2)、删除不能使用二级索引,应尽量使用聚簇索引

3)、如果初始化记录中的id不连续,sessio1执行delete语句的时候是不是不会锁住插入的记录

Session1

Session2

Locks

begin;

begin;

 

insert into ep(e_id, name, create_at) values(100, 'stt', '2022-12-04 00:00:00');

 

 

 

insert into ep(e_id, name, create_at) values(100, 'ssd', '2022-12-04 00:00:00');

 

select * from epG;
id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13
id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13
id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13
id: 4
e_id: 100
name: stt
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:41:47

select * from epG;
id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13
id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13
id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13
id: 5
e_id: 100
name: ssd
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:44:46

 

delete from ep where e_id=100 and create_at <= '2022-12-02 00:00:00';

 

no lock

三:如何解决

先说下最终的解决方式是删除事务和删除动作;删除动作是通过另外的任务去执行。



Tags:mysql锁   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
最全MySQL锁详解(含悲观+乐观锁+行锁+表锁+页锁等)
我们在操作数据库的时候,锁的冲突是影响数据库并发访问性能的一个非常重要因素,从这一角度来说,锁对于数据库而言就显得尤为重要。今天分享MySQL相关的最全锁@mikechen01MySQ...【详细内容】
2023-01-05  Search: mysql锁  点击:(298)  评论:(0)  加入收藏
mysql锁-从实战中理解
mysql锁可能是数据库知识篇幅中普遍比较难理解的一个知识点!以前对锁理解的也是停留在八股文的的阶段,经历了这次生产问题之后重新学习了问题表现:早上刚到公司还没进入状态,就...【详细内容】
2023-01-03  Search: mysql锁  点击:(171)  评论:(0)  加入收藏
一次解决mysql锁表问题的经历
查看mysql执行的线程 show full processlist; 查看mysql 事务处理列表 select * from information_schema.INNODB_TRX 杀死事务进程 kill 16490...【详细内容】
2021-04-30  Search: mysql锁  点击:(515)  评论:(0)  加入收藏
一次并发插入死锁带来的“教训”,我才清楚这些MySQL锁知识
最近遇到一个由于唯一性索引,导致并发插入产生死锁的场景,在分析死锁产生的原因时,发现这一块还挺有意思的,涉及到MySql中不少的知识点,特此总结记录一下。 一、MySql常见的锁谈...【详细内容】
2021-02-19  Search: mysql锁  点击:(363)  评论:(0)  加入收藏
深入分析解读MySQL锁,解决幻读问题
前言今天就为大家介绍一下MySQL中锁相关的知识。本文在没有特别声明的情况下,均是默认InnoDB引擎,如涉及到其他引擎或者数据库则会特别指出。什么是锁锁是一种用于保证在并发...【详细内容】
2020-10-19  Search: mysql锁  点击:(261)  评论:(0)  加入收藏
大牛总结的MySQL锁优化,写得太好了
【51CTO.com原创稿件】随着 IT 技术的飞速发展,各种技术层出不穷,让人眼花缭乱。尽管技术在不断更新换代,但是有些技术依旧被一代代 IT 人使用至今。 图片来自 PexelsMySQL...【详细内容】
2020-02-18  Search: mysql锁  点击:(336)  评论:(0)  加入收藏
MySQL锁详细讲解
本文章向大家介绍MySQL锁详细讲解,包括数据库锁基本知识、表锁、表读锁、表写锁、行锁、MVCC、事务的隔离级别、悲观锁、乐观锁、间隙锁GAP、死锁等等,需要的朋友可以参考一下...【详细内容】
2019-12-24  Search: mysql锁  点击:(342)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(7)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(11)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(10)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(25)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(9)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(28)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(49)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(53)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(54)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(85)  评论:(0)  加入收藏
站内最新
站内热门
站内头条