大数据、高并发下查询不到数据(实际数据存在)
请求QPH在50万左右这个量级
表单数据在5000万到1亿这个数据量
首先执行的是firstOrCreate()方法🙅(由于要分表,现在没法用,只能先查询,然后没有记录再去创建新记录)
然后捕获了唯一索引的异常,捕获后再去查询,但是查不到数据,这种情况下该怎么解决?
已经是在队列里了
求大佬支招~
try {
$watchLogModel = WatchLogModel::suffix($suffix)
->where('transId', $transId)
->first();
if (!$watchLogModel) {
$watchLogModel = new WatchLogModel();
$watchLogModel->setTable('watch_log_' . $suffix);
$watchLogModel->transId = $transId;
$watchLogModel->save();
} else {
$watchLogModel->setTable('watch_log_' . $suffix);
}
} catch (QueryException $queryException) {
if ($queryException->getCode() == '23000') {
//捕获唯一索引异常,然后去查记录
$watchLogModel = WatchLogModel::suffix($suffix)
->where('transId', $transId)
->first();
//这里的查询结果有时候是null
} else {
throw $queryException;
}
}
是不是上了读写分离,写入的时候还没同步到读库的时间差问题
读写分离 强制走写库看看
实际有遇到过这个问题,最开始也是通过你这种通过捕获数据库异常解决,后来改成了
Redis Lock
,也就是加锁,后面的等前面处理完,然后就世界和平了高并发查不到正常,都还没来得及写入,肯定就查不到了。 通常加缓存,缓存在放队列写入,查的时候缓存优先
要不改为ON DUPLICATE KEY UPDATE?
如果 DB 层没有做读写分离,应该关注 隔离级别 设置
我猜测你的 DB 应该是 RC 及以上的隔离级别,T1 事务插入数据后还未提交事务,然后其他事务插入报错,但这个时候是查不到这条数据的,但感觉是很边界的情况。
主从延迟呗,这边写了,从数据库还没更新所以查不到,可以强制读主数据库
你这个方法是在队列里面?
写一个接口出来,接口里面去查询这条记录, 日志记录一下结果. 查询为null的时候, curl一下这个接口,
我建议先了解一下业务需求,对写入的时效性是否有很高的要求,如果要求不高可以使用队列进行消化,尤其是 laravel 可以使用 唯一任务 来针对主键加锁来控制队列消费。
如果时效性要求较高,则可以考虑使用数据库事务和行锁进行处理。
我碰到过,和事务隔离级别有关,RR隔离级别查不到,RC可以,解决方法是getPdo()->exec('set session transaction isolation level read committed')