一次线上 update SQL调优分享

这几周系统访问量也是居高不下,不出意外系统又出现瓶颈了,大量用户反馈判题结果响应太慢;经排查,又是关于SQL的问题

业务背景

一个类似于力扣在线做题的代码评测模块,用户提交判题任务后,后台会进行异步判题,前端会轮询判题结果,如下图

线上问题

大量的用户在前端提交后,一直都轮询不到判题结果。经代码排查,发现问题就出现在判题结果写库逻辑,耗时竟然有1s多。

而我们的判题结果写库 分为两个步骤

  1. 更新 这道题的提交数量,正确率等等
bash 复制代码
 可以简单理解为       
 update  xxxx  where  topic_id = xxx
 ​
 //topic_id是索引
  1. 将用户的判题结果写库
lua 复制代码
 逻辑较多,可以理解为多次insert,和用户维度的update.

问题分析

查看方法调用日志, 发现 第一个步骤(更新这道题的提交数,正确率)占据了80%的耗时。

当我们 update xxxx where topic_id = xxx时,MySQL会对topic_id 索引加行锁,由于第一个步骤和第二个步骤又在同一个事务。

当高并发时,用户做题是多对一的关系,大量用户可能都在写一道题,造成题目ID的行锁竞争激烈,更新题目提交数、正确率的行锁在更新玩之后不会释放;还需等待第二步,将结果写库完后(等事务执行完后)。这样行锁的无效持有时间或者叫行锁的持有粒度就增加了。

解决问题

按问题解决,直接减小行锁的粒度。

将1、2两个步骤交换下顺序。交换后逻辑变为:

  1. 将用户的判题结果写库
lua 复制代码
 逻辑较多,可以理解为多次insert,和用户维度的update.
  1. 更新 这道题的提交数量,正确率等等
bash 复制代码
 可以简单理解为       
 update  xxxx  where  topic_id = xxx
 ​
 //topic_id是索引

你可以简单的理解为 原先老逻辑是 先update,再insert。现在是先insert再update;这样行锁的持有粒度就降低了。

经此一役,判题结果写库的逻辑从原来的 400TPS直接拉高到2000多TPS!!!

总体

再总结一下,本篇通过线上判题结果的业务逻辑 分享SQL读写的调优小技巧,先insert再update,可以降低行锁的粒度,提高TPS。

相关推荐
Irene19915 分钟前
SQL示例:外键约束是关系型数据库中用于建立两个表之间链接的一种规则
mysql
dadaobusi9 分钟前
PCIe的ATS和PRS
java·网络·数据库
汽车仪器仪表相关领域11 分钟前
HORIBA MEXA-584L 全功能汽车排放废气分析仪:便携精准排放检测 + 多参数同步测量 + 国六 / 欧 7 合规适配,汽车检测与调校的黄金标准
服务器·数据库·人工智能·功能测试·汽车·压力测试·可用性测试
qq_3660862221 分钟前
SQL 中 OR 与 UNION ALL选择指南
数据库·sql
正在走向自律28 分钟前
时序数据库技术内幕:从大数据存储模型看工业级时序数据库的设计与落地
大数据·数据库·时序数据库·工业物联网存储·tsfile 存储引擎·大数据时序技术·物联网数据治理
zshs00030 分钟前
从 Raft 到 MySQL:我是怎么推导出半同步复制原理的
数据库·分布式·mysql
环流_31 分钟前
redis中list应用场景
数据库·redis·list
东风破13733 分钟前
DM8达梦分布式计算数据库集群DPC安装部署学习记录
数据库·学习
fox_lht35 分钟前
第十二章 泛型、接口和生命周期
开发语言·后端·rust
ikoala35 分钟前
用了几周明基 RD280UG,我终于明白程序员为什么需要一台“专用显示器”
前端·后端·程序员