asmile1993 最近的时间轴更新
asmile1993

asmile1993

V2EX 第 574002 号会员,加入于 2022-03-01 15:22:58 +08:00
asmile1993 最近回复了
原来的操作逻辑有问题,你第一步是查询用户积分总额,然后更新积分总额,最后再将积分余额插入到积分记录表中,第一步只读查询并没有加锁,因此是可以并发的,这可能导致并发的线程读取到的余额是不一致的,又因为你积分总表的更新逻辑是正确的,这会造成积分记录表中记录的积分余额错乱,而积分总表中的余额又是正确的。

-- 步骤一:先变更,这样会锁住 `uid`='22' 这条记录,别的会话只能查询,不能变更
UPDATE `api_credits` SET `credits1`=`credits1`-'100' WHERE `uid`='22' AND `credits1`>='100'
-- 步骤二:拿到变更后的最新的积分余额
SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1
-- 将步骤二中获取到的积分余额插入到积分记录表中
INSERT INTO `api_credits_log` SET `uid`='22', `cid`='3', `credits`='100', `balance`='79900', `time`='1701001020'

将这三步放入到同一个事务中
从哪本书截的图?看这文字描述,我觉得这本书质量不是很高。

1) 假设 Q2 能利用上索引 (a, b),那么由于 a 是范围查询,根据高性能 MySQL 中的知识,可以知道“如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找”, 这里说的无法使用索引优化查找,是指“不能用索引快速定位”,但"快速过滤"是可以做的。

2) 由 1 可知,索引(a, b) 中,只有列 a 能用作索引快速定位,而列 b 不能用来快速定位,但 MySQL 有索引下推优化,因此对于列 b 来说,可以利用 ICP 来达到在索引遍历中快速过滤,从而减少回表次数。

有点没看懂你这个例子的回答,一直说索引有序是什么意思,虽然有关系,但有点答不对题,让人疑惑。
我估计楼主在 create_time 字段上建立了单列索引,查询具有 ORDER BY 或 GROUP BY 和 LIMIT 子句的情况下,控制优化器是否尝试使用有序索引而不是无序索引、文件排序或其他优化。 每当优化器确定使用它可以更快地执行查询时,默认情况下都会执行此优化。
因为这种算法不能处理所有可能的情况(部分原因是假设数据的分布总大体是均匀的),所以在某些情况下,这种优化可能是不可取的。 在 MySQL 5.7.33 之前,无法禁用此优化,但在 MySQL 5.7.33 及更高版本中,虽然它仍然是默认行为,但可以通过将 prefer_ordering_index 标志设置为 off 来禁用它。可以参考下文档 https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html

解决方案 1:禁用 prefer_ordering_index 优化(不推荐),可能导致 pt 工具或其他根据 order by 的查询耗时过长(无法利用最优索引)
解决方案 2:order by create_time, 其他字段(推荐),加上除主键外的其他列,来达到禁用 create_time 上索引的效果
解决方案 3:使用 ignore index idx_name 来禁用掉 create_time 上的索引
解决方案 4:使用联合索引(推荐)
2022-11-17 19:33:40 +08:00
回复了 qiyong 创建的主题 程序员 面试中遇到的一道 sql 题
with goods_sales as(
-- 获取每种商品的总销售额
select distinct
g.id as goods_id,
g.name as goods_name,
g.group_id,
gg.name as group_name,
sum(gsr.sales_volume) over(partition by g.id, g.name, g.group_id, gg.name) sum_goods_sales_volume,
sum(gsr.sales_volume) over(partition by g.group_id, gg.name) sum_group_sales_volume
from goods g
inner join goods_group gg on g.group_id= gg.id
inner join goods_sales_record gsr on g.id= gsr.goods_id
order by sum_goods_sales_volume desc -- 以商品的总销售倒序排列,并取前三名
limit 3
)
select goods_id,
goods_name,
group_id,
group_name,
sum_goods_sales_volume, -- 每种商品的总销售额
sum_group_sales_volume -- 每种分类的总销售额
from goods_sales
order by sum_group_sales_volume desc, sum_goods_sales_volume desc -- 以每种分类的总销售额、商品的总销售倒序排列
2022-10-24 17:20:08 +08:00
回复了 NoKey 创建的主题 程序员 统计一下,今天多少公司发橙子🤣
羡慕,我只有一句祝福
2022-10-09 16:55:38 +08:00
回复了 OeO 创建的主题 MySQL 请教 sql 数据表设计的问题
可以考虑用 json 数据类型来存储这种数据,比如 json 数组,数组中每个对象是一个 json 对象来存储车辆信息
2022-09-20 14:03:06 +08:00
回复了 coderstory 创建的主题 MySQL 关于 MYSQL8 时间类型字段的一些疑问
@coderstory 我的版本是 8.0.26 ,加索引操作没问题
2022-09-20 11:42:37 +08:00
回复了 coderstory 创建的主题 MySQL 关于 MYSQL8 时间类型字段的一些疑问
Q1: mysql 的那两个默认值为什么会变
CURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().
CURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().

Q2: 为什么加索引提示错误默认值
执行成功了,你是不是分别有 Table2 和 table2 这两张表?看看自己的 lower_case_table_names 参数是否为 0
2022-07-27 17:31:52 +08:00
回复了 sunmoon1983 创建的主题 MySQL 求大神解答,这种 sql 应该怎么写?
-- 创建张维表,结构如下, 划分好每个 code 的年龄范围
-- 也可以不创建,用子查询创建个临时的结果集
create table code_age(
code varchar(20),
age_start varchar(20),
age_stop varchar(20)
)

-- 再根据 code 和原表 table1 关联,并根据 age 来筛选
select a.*
from table1 a inner join
code_age b
where a.code = b.code
and a.age > b.age_start
and a.age < b.age_stop
2022-05-27 11:21:26 +08:00
回复了 zzzain46 创建的主题 MySQL 如何高效地取连续三个月同一时间有交易的商户
@thinkingbullet MySQL 版本得是 8.0 的
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   982 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 12ms · UTC 20:23 · PVG 04:23 · LAX 13:23 · JFK 16:23
Developed with CodeLauncher
♥ Do have faith in what you're doing.