代码拉取完成,页面将自动刷新
explain
查看走的是否是索引,本项目查询后发现走的是索引,因此不是索引的问题select count(1) from tbname
show profiles
,找到上条查询对应的 Query_ID
SHOW PROFILE FOR QUERY ${上面的Query_ID}
,查看时间分布send data
上,对此网上有种说法是,大数据字段,如text,很长长度的varchar等,mysql会将部分数据放在溢出页
里面,
因此还会走一遍磁盘扫描。但本项目直接查的count(1)
,没有查询大字段,因此该说法不适合当前情况。继续分析发现,查询时,系统磁盘IO很猛,
按理查的是索引,在内存里面,不会有这么多的磁盘IO,遂想到修改配置文件my.cnf
,增大innodb_buffer_pool_size
,
增大的原则是Data_length + Index_length 值的总和的110%
。修改后重启,查询降低到0.1s,问题解决。(注意第一次就有点慢,
因为刚刚启动,索引数据还没有加载到内存,后续查询很快)
select count(detail)
,查询大字段确实比查主键慢,当然原因在于索引,没有涉及到溢出页
的验证压测方式:通过 jmeter 模拟 100 用户同时下单
标题 | 方式 | 平均响应时间(去掉启动后的第一次) | 数据库数据 | 结论 | 补充 |
---|---|---|---|---|---|
秒杀一 | * 无事务 | (16+15+10) / 3 =14ms | * 库存剩余16件,销量79件,且数据库销量有多条相同记录。取的是其中一次测试的数据 * 随着测试次数的增加,库存越来越接近0,超卖越来越少。原因未知,也可能是偶然事件 | * 超卖 * 由于销量的创建是懒存储,当有第一笔订单时才添加销量。因此出现了多条记录,原理类似某些错误单例模式在并发情况下出现的多个实例 * 库存销量之和可能大于100,也可能小于100,原因在于库存和销量的新增不是原子操作,更新库存与更新销量可能分别是两笔订单最后处理的数据库 | |
秒杀二 | * 方法级别添加事务@Transactional | (32+48+29)/ 3 = 36ms | 库存剩余53件,销量47件,且数据库销量有多条相同记录。库存销量之和始终为100 | * 超卖 * 事务保证了更新库存和更新销量的一致性,因此保证了两者之和为100不变 * 事务增加了消耗,相对而言响应较慢,超卖更多 (也可能是偶然,毕竟差距不大) | |
秒杀三 | * 悲观锁(有事务) | (20+12+11) / 3 =14ms | 库存剩余0件,销量100件,始终如此,没有超卖 | * 成功秒杀 * 响应很快,并没有因为锁响应速度收到影响 | 一开始没有加事务,发现和方式一效果一样,这是因为悲观锁,或者说排他锁的释放时机是事务结束,没有事务锁不生效 |
秒杀四 | * 乐观锁(无事务) | (20+12+11) / 3 =14ms | 库存剩余0件,销量100件,始终如此,没有超卖 | * 成功秒杀 * 响应很快,并没有因为锁响应速度收到影响 * 虽然最终的库存和销量是正确的,但过程中查询的两者之和不为100,因为两步是在不同的乐观锁逻辑之中,不像悲观锁,可重复度级别的事务保证了和始终100,这对业务逻辑影响较小,可以通过其它方式实现 | |
秒杀五 | * 分布式锁+线程池(coreSize,maxSize=1) | (23+10+12) / 3 =15ms | 库存剩余0件,销量100件,始终如此,没有超卖 | * 成功秒杀 * 响应很快,并没有因为锁响应速度收到影响 * 将mysql数据库事务可能的问题转给redis,然后将任务存储到队列串行执行 | * 虽然没有测试吞吐量,但考虑到redis相对mysql,具体更高级别的响应能力,因而此种方式可能有更高的吞吐量 * 由于是异步存储到数据库,可能出现订单数据的延迟 |
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。