秒杀场景下MySQL的低效--原因和改进
如果无法正常显示,请先停止浏览器的去广告插件。
1. DTCC2013
秒杀场景下MySQL的低效
--原因和改进
@淘宝丁奇
2009-8-22
2. DTCC2013
1. 秒杀/热卖商品背景
2. 性能问题
3. 几种解决方案
3. 秒杀/热卖商品背景
a)商品库存是有量的
b)买家下单以后库存要减掉
c)不能减成负数
DTCC2013
4. 秒杀/热卖商品背景
DTCC2013
基本逻辑
Start transaction
Insert …
Insert …
Update set 库存 = 库存 – n where …
Commit
5. 秒杀/热卖商品背景
DTCC2013
6. 秒杀/热卖商品背景
DTCC2013
多个用户
Start transaction
Insert …
Insert …
Update set 库存 where 商品id…(互相等待)
Commit
原因:InnoDB的行锁
7. 性能问题
原因是:
行锁串行导致性能下降吗?
分析:
问题可以简化为,很多线程更新同一行
CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB;
Insert into t1 values($i, 2147483647);
插入50行数据
DTCC2013
8. 性能问题
DTCC2013
tps
25000
20000
15000
tps
10000
5000
0
1
2
3
4
5
6
7
8
9
10
20
30
50
线程数
1
2
3
4
5
6
7
8
9
10
20
30
50
阶段结论 : 6个线程并发各自更新一行性能最高
TPS
6100
12700
16357
18570
19160
19160
18320
17000
16577
15700
15000
14250
13000
9. 性能问题—现象
DTCC2013
tps
20000
18000
16000
14000
12000
10000
tps
8000
6000
4000
2000
0
1
6
12
24
48
96
192
384
768
1536
线程数
1
6
12
24
48
96
192
384
768
1536
tps
6100
19160
14000
10000
9800
7000
3600
2000
600
150
10. 性能问题—分析
DTCC2013
1、随着并发线程增加,tps急剧下降
2、每个商品有128个线程并发请求的时候,tps已经跌到600
不可接受
3、 坏消息是,秒杀的时候,一个商品何止128个人来抢?
11. 性能问题—分析
DTCC2013
当并发线程多时,MySQL在做什么
因此,串行并不是问题,问题是InnoDB内部存在太多线程
12. 解决方案
在那之前,先回顾这张图片
DTCC2013
13. 解决方案 1 -- 关掉死锁检测
方案特点:
很直接
很暴力
正常的业务死锁会变成超时
不治标
除掉老大,还有老二,问题的症结没有解决
DTCC2013
14. 性能效果
DTCC2013
20000
线程数 TPS1 TPS2
1 6100 6100
6 19000 19000
12 14000 14000
24 12000 12000
48 9800 10000
TPS1
96 7000 8500
TPS2
192 3600 7200
384 2000 4800
768
600 2500
1536
150 1300
18000
16000
14000
12000
10000
8000
6000
4000
2000
0
1
6
12
24
48
96
192
384
768
虽然啊在1536线程时性能是8倍,但依然不可接受
1536
15. 性能效果分析
并发
线程
为什么平时我们没有这个问题?
DTCC2013
16. 解决方案 2 – 关于症结
DTCC2013
固定车道的公路,最流畅的方式是什么
17. 解决方案 2 – 系统最优值
DTCC2013
在固定的硬件条件下、每个系统都有一个对应的状态最优值
InnoDB的线程数
将排队队列提到进入引擎层前
18. 解决方案 2 – 排队
DTCC2013
19. 解决方案 2 – 排队
DTCC2013
20. 解决方案 2 – 性能
DTCC2013
20000
18000
16000
14000
12000
TPS1
10000
TPS2
TPS3
8000
6000
4000
2000
0
1
6
12
24
48
96
192
TPS不随着线程数增加而下跌,维持在1.5w
Update /*UPDATE_STOCK 1*/ t set b=b-1 where a=1;
384
768
1536
21. 解决方案 3 – 排队优化
想想排队买票的事儿
排队优化,成组提交
DTCC2013
22. 解决方案 2 – 排队优化
DTCC2013
23. 解决方案 2 – 排队优化
DTCC2013
24. 解决方案 2 – 排队优化
DTCC2013
25. 解决方案 3 – 性能对比
DTCC2013
100000
90000
80000
70000
60000
TPS1
TPS2
50000
TPS3
40000
tps4
30000
20000
10000
0
1
6
TPS 稳定在8.5w
12
24
48
96
192
384
768
1536
26. DTCC2013
解决方案 3—限制
语句:
update /*UPDATE_STOCK 6784 1 '1' 'H<=Fquantity‘*/
tbl_name
set withholding_quantity = withholding_quantity + 1,
gmt_modified = NOW()
where auction_id = 6784
and (withholding_quantity - 1) <= quantity;
“太定制”
1、跟业务逻辑绑定较紧密
2、使用常见必须符合“可组提交”的限制
26
27. 总结
DTCC2013
多线程并发下,InnoDB内部要做死锁检测等操作,对性能
影响及其严重
明确的串行事务,则server层串行
Group commit减少引擎执行次数
28. 提问时间
DTCC2013
谢谢大家!
28