1.MySQL/Percona 5.6/5.7 秒杀场景优化 杨德华@PHPCON 2017
2.个⼈人介绍 • 杨德华 • 曾供职于阿⾥里里集团数据库技术团队 • 经历5年年双⼗十⼀一MySQL⼤大考 • ⽬目前供职 杭州数列列科技 • 微信号:whitepoplar
3.压测场景 • 压测⼯工具 sysbench0.5(官⽅方认可的压测⼯工具) • 事务隔离级别均为READ-COMMITTED. CPU 32cores. BP15G。数据放在SSD,⽇日志放在SAS盘。 • thread_pool_size=16;thread_pool_oversubscribe=1; innodb_thread_concurrency=32; • CREATE TABLE `test_update` ( • `id` int(11) NOT NULL AUTO_INCREMENT, • `stock` int(11) DEFAULT NULL, • PRIMARY KEY (`id`) • ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 • insert into item.test_update (id,stock) value(1,500000);
4.压测场景 • 更更新语句句update test_update set stock =stock -1 where id = 1 and stock >3;
5.5.6版本的压测数据 • 256以上并发线程的压测数据 • 更更新语句句update test_update set stock =stock -1 where id = 1 and stock >3;
6.5.7版本压测数据 • 更更新语句句update test_update set stock =stock -1 where id = 1 and stock >3;
7.秒杀场景解读 • 秒杀/热点更更新场景 • 互联⽹网电商常⻅见场景 • 活动预热->商品聚集⼤大量量⼈人⽓气->瞬间下单
8.⽣生活中的场景 • 思考:⽣生活中有哪些场景和秒杀类似?
9.场景抽象 • 处理理请求是并⾏行行,DB节点最后变成了了串串⾏行行 • 多个应⽤用节点向⼀一个DB节点的⼀一⾏行行发送数据处理理请求 • DB要保证数据的ACID以及⾼高性能
10.⽬目录 • ⼀一个事务之旅(简化版) • DB端:线程池、事务、死锁检测基础概念 • DB端:性能压测数据对⽐比、结论 • 应⽤用端如何优化?
11.MySQL架构
12.⼀一个 update事务 之旅(简化)
13.⾼高并发的 update事务 热点库存扣减情况
14.⾼高并发访问秒杀场景下 • 数千个⽼老老王进⾏行行了了点击购买,这时候DB会出现什什么情况? • 连接数增加,MySQL Server的线程切换成本增加 • 每个update都要等待前⾯面的update释放锁,都会进⾏行行死锁检测, 请求越多,检测等待越久
15.⽬目录 • DB端:⼀一个InnoDB事务之旅 • DB端:线程池、事务、死锁检测基础概念 • DB端:性能压测数据对⽐比、结论 • 应⽤用端如何优化?
16.MySQL Server默认线程模型
17.线程池性能 读写场景 128个线程并发 原⽣生版本性能 降低
18.线程池性能 只读场景
19.MySQL线程池的发展路路径 • MySQL处理理客户端对应的参数是thread_handling •no-threads:debug模式,DB只创建⼀一个链接和线程 • one-thread-per-connection 每⼀一个客户端链接,服务端都会创建对应的⼀一 个线程来服务,然后根据thread_cache来进⾏行行缓存线程信息以便便重复使⽤用 • dynamically-loaded 线程池模式 服务端预先根据设置的线程池⼤大⼩小,创建 好线程,等客户端创建connections到Server后,调度线程池⾥里里⾯面的线程来 进⾏行行排队服务,可以理理解为线程池帮助服务端做了了⼀一下缓冲,减少对后端 的影响,后端可以更更专注于本身的事情。
20.MySQL线程池的发展路路径 • 线程池模式在MySQL 5.5 企业版,提供了了⼀一个线程池的Plugin,专⻔门 针对MySQL的活跃线程超过⼀一定数量量性能会⼤大幅下跌的场景。线程池 • 通M过ar限iaD制B了随了进后⼊也入到开存发储了了引线擎程级池别功的能线,程,提⾼高了了MySQL性能的稳定。 但并没把开代源码。进⾏行行了了开源 • Percona基于MariaDB的线程池,也增加了了线程池功能,我们压测的 版本Percona-5.6.25默认带有线程池功能
21.Thread Pool下的线程模型
22.MySQL线程池的实现
23.线程池总结 • 每个线程都消耗额外的内存,⽽而且每次线程间的切换都 会消耗CPU周期并丢弃CPU⾼高速缓存中的数据。 • 线程池减少了了连接和线程切换和维护的成本 • Percona和MariaDB⽐比官⽅方社区版增加了了线程池⽀支持
24.InnoDB死锁检测 • 先看⼀一些现实⽣生活中的例例⼦子
25.InnoDB事务 • ACID(原⼦子性,⼀一致性,隔离性,持久性) • InnoDB事务源码结构体,66个数据变量量 • 需要关注的⼏几个锁结构 • 事务锁结构 trx_locks • 锁结构 lock_t • 事务结构 trx_t
26.InnoDB 事务锁
27.InnoDB内部锁申请顺序
28.InnoDB死锁检测 • 1.什什么是死锁? • 2.InnoDB什什么时候会检测死锁? • 3.数据库系统如何处理理死锁? • 4.InnoDB的死锁检测过程?
29.什什么是死锁 • 《数据库系统实现》第⼋八章第⼆二节这样定义死锁 • 并发执⾏行行的事务由于竞争资源⽽而到达⼀一个存在死锁的状态: • 若⼲干事务的每⼀一个事务都在等待被其他事务占⽤用的资源, 因⽽而每个事务都不不能取得进展。
30.死锁的形象认识 • • 堵两⻋位车现⽊木象匠钉地板,⼀一位握⼀一把锤⼦子,⽽而另⼀一位没有锤⼦子,却有钉⼦子
31.数据库系统如何处理理死锁
32.涉及死锁检测的例例⼦子 • create table test_lock(id int auto_increment primary key ,stock int) engine=innodb; • insert into test_lock(id,stock) value(1,50); • innodb_lock_wait_timeout:⽤用来控制锁等待超时;read-commited
33.MySQL的死锁检测和回滚
34.关闭死锁检测的⼀一些故事..
35.性能压测对⽐比 • 对着四个版本进⾏行行了了8,16,32,64,128,512,1024个并发线 程的压测 • A.MySQL5.6.19 原⽣生版本 • B.MySQL5.6.19 增加死锁检测关闭 (5.6.1.9+no deadlock check ndlc) • C.Percona5.6.25 原⽣生版本 (percona+tp) • D.Percona5.6.25增加死锁检测关闭 (percona+tp+nldc)
36.• 8,16,32个客户端下,原⽣生版本的TPS⽐比后⾯面三个场景的TPS要⾼高.但这么 少的连接,业务很难会只给这么少连接
37.• 64个和128个客户端连接 • 原⽣生版本+关闭死锁检测 TPS最⾼高
38.• 256个客户端连接下,原⽣生版本+关闭死锁检测 TPS最⾼高,原⽣生版本的 TPS已经降低到2000+
39.• 512个客户端连接下,5.6.19TPS降低到600+
40.• 1024个客户端连接下,5.6.19TPS降低到30
41.5.6版本的压测数据 • 256以上并发线程的压测数据
42.5.7版本压测数据
43.关闭死锁检测-压测结论 • 关闭死锁检测后,5.6.19/5.7.19版本在1024个客户端并发连接情况下 可以从30TPS提升到3924 • 应⽤用程序⽆无须更更改代码,减库存性能提升120倍;
44.线程池—压测结论 • Percona版本由于有线程池做了了⼀一层连接的并发控制,间接减少了了数 据库内部的线程上下⽂文切换和锁竞争 • 在1024个客户端并发连接的情况下,TPS是5.6.19+关闭死锁检测的接 近1倍;
45.总体策略略—压测结论 • Percona版本+线程池调优+关闭死锁检测的情况下,在1024个客户端 并发连接下,性能有⼩小幅度提升
46.落地措施-压测结论 • 5.6.19版本,谨慎考虑可以只增加关闭死锁检测的补丁代码,实现最 ⼩小⻛风险升级,关闭死锁检测后,依赖DBA审核SQL和锁等待超时回滚事 务. • 5.7.19有官⽅方⽀支持的参数关闭死锁检测 • 但在微服务架构下,客户端对DB的链接越来越多,建议最终升级成 Percona版本,利利⽤用线程池的优势来提升DB的稳定性
47.问题回顾 • 1.MySQL线程池机制减少了了内部线程竞争、CPU上下⽂文切换 • 2.简化业务逻辑,key-value式的SQL场景可以关闭死锁检测来 提升DB性能,如果真有死锁,通过锁等待超时来回滚事务
48.⽬目录 • DB端:⼀一个InnoDB事务之旅 • DB端:线程池、事务、死锁检测基础概念 • DB端:性能压测数据对⽐比、结论 • 应⽤用端如何优化?
49.其他讨论 • DB端还可以做的优化 • 根据事务信息做预排队 • 应⽤用端可以做的优化 • 根据连接数据信息预排队,和上⼀一条类似
50.热点库存 架构
51.场景抽象 • 多个应⽤用节点向⼀一个DB节点的⼀一⾏行行发送数据处理理请求 • 应⽤用处理理请求是并⾏行行,DB节点最后变成了了串串⾏行行 • DB要保证数据的ACID以及⾼高并发连接下的⾼高性能
52.• 谢谢⼤大家 结束