事情是这样的,最近公司需要统一更改一些老表的主键类型,以前表的主键都是 int 类型,这次要改成 bigint。
然后我整理的时候发现一张表,里面竟然有 5 亿的数据,之前排查问题优化过几条慢 sql,这个表的查询竟然没进慢 sql 名单,有点突破我的认知,平日使用也没啥问题。
后面还发现了好多张 3000w 到 8000w 的表,里面字段数量也比较正常,10个左右,也在好好的用着,所以不要死板的听网上说超过 1000w、2000w 就要分表啥的。
避免提前优化,出了问题再处理才是王道,因为你提前做的一些准备,很大可能是无用功,浪费了感情和精力。
话说回 5 亿数据的这张表。
当天晚上执行修改类型语句时,由于执行时间超过了自建 sql 平台的时间阈值(平台发现一条 sql 执行超过 2 小时就会主动关闭连接)
而这个修改类型的 modify 语句又不能分开执行,只能一次性执行,所以就尬住了。
当时还有一条方案是绕开 sql 平台, 让 dba 在外面直接执行,后面由于时间太晚了,所以就等第二天再说。
到了第二天,分析了下这张表,发现其实之前的数据都是没用的,可以进行归档,也就是把 21 年的数据移到另一张表中,只留下 22 年的数据。
这张表是有时间索引的。
我查了下 21 年的数据大概有 3 亿多,删除这些数据后,估计能减少一半多 modify 的时间,而且本身这张表也是要归档的,只是今年忘了做了(说明一直没遇到查询慢的问题)。
所以方案就变成,先进行数据归档,即 insert into 21年的数据到新表中,然后 delete 这张表里面 21 年的数据,然后再 modify 更改类型。
insert into 和 delete 语句都很简单,但是由于数据量太大,避免长事务的问题,dba要求我们自行拆分 sql 语句给他执行。
当时我就寻思着:这拆分也得开发来拆?DBA 就仅仅是个无情的执行机器?
行吧,拆就拆,然后我就将 insert into 拆成了 100 条, delete 也拆成了 100 条给了 DBA。
当天晚上 DBA 又执行了一波,不过当时的 delete 有好几条失败了,他询问我,这个表当前还会有请求让其变更吗?
我说不可能,因为这张表相当于流水表,删除的是 21 年的数据,当前不可能有 21 年数据的变更,但确实是报错了,我看了下错误,锁超时。
当时我就奇怪,为什么有锁等待超时,现在不可能有业务在操作 21年的数据。
后面我才发现 DBA 是在并行执行多条 delete 语句。
于是,我在群里跟 DBA 说应该因为你并行执行多条 delete ,它们之前有竞争关系,而一条 delete 删除的数据挺多的,所以等锁等超时了。
DBA 来了句:有 id 范围限制的,delete 之间应该不会有冲突的。
我简化下,几条 delete 语句如下所示:
delete from yes where date < '2022-06-25' and (id >= 1 and id <10)
delete from yes where date < '2022-06-25' and (id >= 10 and id <20)
delete from yes where date < '2022-06-25' and (id >= 20 and id <30)
好了,背景交代完毕,看到这你可以思考一下,并行执行上面这几条 delete 语句,它们之间是否会发生竞争锁呢?
当前事务隔离级别为:可重复读隔离级别,mysql 版本5.7+
答案是它们之间会冲突,会竞争锁。
一切拿事实说话,为了这个事实首先我们得有一张表。
CREATE TABLE `yes` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`address` varchar(45) DEFAULT NULL,
`date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
先来看看小数据量,可以看到数据库就 5 条数据。 这时候我在客户端 A 执行一条 delete 语句:
delete from yes where date < '2022-06-25' and (id > 1 and id <3)
不提交事务。
此时在客户端 B 执行另一条 delete语句:
delete from yes where date < '2022-06-25' and (id >= 3 and id <5)
可以看到,此时发生了阻塞:
是不是有点奇怪?看起来它们之间没有冲突的呀?
让我们执行下 select * from information_schema.innodb_locks;
,看看锁的详情:
可以看到 lock_mode 是 X 锁,说明是排他锁,然后 lock_type 是 RECORD 说明是行锁。
lock_index 是 PRIMARY ,说明锁的是主键索引, lock_data 是 3,也就是锁的是主键 ID 为 3 的那条记录。
此时我们就知道了,确实发生了竞争,且竞争之地发生在主键索引上,用的是行锁,冲突的那行就是 ID 为 3 的那行。
我们再来执行select * from sys.innodb_lock_waits \G;
,看下对应的 lock_id 是不是我们执行的语句:
可以看到,确实是 10586 被阻塞了,对应的就是客户端 B 执行的那条语句。
这个实验已经和那天晚上阻塞的情况吻合了,当然结果是结果,重要的是搞清楚为什么会这样。
让我们继续往下看。
我们来 explain 一下这个 delete 语句:
发现 delete 语句用的是主键索引,即使 date 列有索引能也能覆盖到条件字段(id),用的也是主键索引。
但是讲道理即使用的主键索引也不对呀,有 id < 3
这个条件,为什么会锁 id=3 这行?
因为在可重复读隔离级别下,实际上范围加锁(id >1)规则是会往后遍历,直到扫描到不满足条件 即 id = 3 的那行,然后停止,因此这条语句最后扫描到的那行恰巧就是 id =3 的这一行,于是锁住了它。
此时另一条 delete 语句执行的时候是需要 id =3 这条记录的行锁(这个没啥疑问吧?),所以就竞争了,然后由于第一条语句 delete 的数据量大,所以执行的久,于是就触发了第二条的锁超时。
好了,通过小数据分析得到的结果已经和那天晚上执行的结果一致,其实到这已经可以结束了,但是为了严谨一些,现在我们拿大数据量来继续实验一次。
为了更加真实,首先我多加了一些字段:
然后随机插入了 1000w 数据:
这时候我在客户端 A 执行 delete 语句:
delete from yes where date < '2022-06-25' and (id > 1 and id <100000)
不提交事务。
此时在客户端 B 执行另一条 delete 语句:
delete from yes where date < '2022-06-25' and (id >= 100000 and id <200000)
同样发生了阻塞,而且一样用的是主键,同样还是竞争的是边界值的那一行 id:100000
:
好了,大数据量的也测试过了,得到一样的结论,这样就能解释为啥当天并行执行多条 delete 语句会出现锁超时的情况。
所以 DBA 的结论是错的,我们来小结一下:
在可重复读隔离级别下,带上索引键和主键通过范围搜索条件来执行 delete 语句,不论数据量大还是小,mysql 都会利用主键索引来扫描记录(我猜测反正都要删数据,即本来就要删除二级索引和聚簇索引的数据,所以索性就用主键索引扫描?)
而范围扫描加锁的数据会扫到第一个不满足条件的记录,即第一个不满足条件的记录也会被上锁,因此并行删除的时候因为边界值产生了竞争关系,又由于 delete 语句执行的时间长,导致了 lock wait timeout 的报错。
好了,分析结束。
话说今天随机插入数据的时候搞了我好久...写了个存储过程来插,但是执行了半天发生一直插不进去,一直在 runing,就非常的纳闷,想着一千万数据也不需要这么久的啊。
后面奇了怪了,于是新建了一张表,分分钟就插成功了。于是又回来看之前的表,看来看去看不出个所以然,于是准备把这张表删了,发现删都删不掉,最终发现我有个小窗口执行的语句把整个表锁了....所以怎么都插不进去。
前后搞了 3 个多小时,最终执行的结果就花了 2 分钟...
难受。
话说回来,这 DBA 是真的懒,感觉他的活都不用动脑,搞啥都是 sql 平台上我们提交sql,由我们的技术负责人审核,审核过了,他在界面上点一下执行就行。
前面说的拆 SQL 这种非业务相关的也得我们拆,给他排的整整齐齐让他执行。
平时我们监控报警,什么数据库 CPU 报警了,也是报警到我们这边,由我们来看具体是什么导致的。
总之,不要过多信任 DBA,一切还是得靠自己,自己行才是真的行,包括 DBA 告诉你的一些结论,还是自己实验最为靠谱。
如果文章有什么错误,还请留言或联系我纠正之~
最近打算换工作的可以了解下我的这个服务:[简历指导和模拟面试] ,已经帮助几个小伙伴拿到大厂的 offer 了。
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/lanJAu9DqD6NhJGhB5eyFA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。