出現(xiàn)一個讓我很廢腦的問題,我有一個接口,使用了ThinkORM,有事務(wù),當請求后,會增加用戶的余額。
剛開始啟動webman運行,很正常,可以按照正常的流程去運行,數(shù)據(jù)也能正常的更新到數(shù)據(jù)庫里。
但是過一會,假定為1個小時,我再次請求這個接口,接口能正常返回,返回接口能看到增加后的余額,增加余額后,我再去余額列表查看,數(shù)據(jù)也能獲取到最新增加的余額增加記錄。
我反復請求接口,都能正常運行,余額列表也能獲取到最新的訂單信息,但是奇怪的是,這個數(shù)據(jù)好像只存在于內(nèi)存中,只有當前的連接能調(diào)用,我用另外的接口去請求最新的余額訂單,返回的卻是1個小時之前的數(shù)據(jù)。
我所有接口的讀操作正常,所有的寫操作都會出現(xiàn)這個問題。
我使用數(shù)據(jù)庫軟件,phpMyadmin和HeidiSQL查看數(shù)據(jù)庫,均無法查到我后面接口請求的數(shù)據(jù),只能查到1個小時前的數(shù)據(jù)。
程序是正常運行的,沒有任何報錯,運行邏輯也很清晰。
但是當我重新啟動webman,我請求余額列表的數(shù)據(jù),包括用戶余額的數(shù)據(jù),后面新增的數(shù)據(jù)都不存在了,請求的都是1個小時前的數(shù)據(jù),因為后面的數(shù)據(jù)根本就沒有實際寫入到數(shù)據(jù)庫里面。重啟webman導致了數(shù)據(jù)庫重新連接。
我使用了redis緩存,但是這個問題不是緩存的問題,我清除緩存,會出現(xiàn)一樣的問題,緩存不可能在我重啟后,就失效。
我被這個問題困擾了2天,后面我嘗試使用webman/log這個插件,分析一下SQL數(shù)據(jù),奇怪的是,竟然不會出現(xiàn)之前那種,請求正常,但是不會實際寫入數(shù)據(jù)庫這種情況了,竟然一切都恢復正常了。
當我將webman/log設(shè)置成false,不運行的時候,問題又會出現(xiàn)。
我之前也懷疑是事務(wù)沒提交,但是根據(jù)運行流程,事務(wù)是肯定運行了,并且也能成功返回數(shù)據(jù),只要我不重啟webman,這些數(shù)據(jù)會一直存在,也會新增,只不過,只要我重啟webman,一切都會回到之前。
因為webman/log會產(chǎn)生大量的日志,調(diào)試的時候能用一下,但是生產(chǎn)的時候不想使用,我想知道可能出現(xiàn)這個問題的原因,或者解決辦法,有沒有大神能告知一二,萬分感謝,下面有一些具體的信息。
我論壇里面找到了二個類似的貼子
http://www.wtbis.cn/q/8570
http://www.wtbis.cn/q/7476
我使用的庫
"require": {
"php": ">=7.2",
"workerman/webman-framework": "^1.5.0",
"monolog/monolog": "^2.0",
"tinywan/exception-handler": "^1.1",
"webman/think-orm": "^1.0",
"psr/container": "^2.0",
"illuminate/redis": "^10.5",
"symfony/cache": "^6.2",
"webman/console": "^1.2",
"topthink/think-log": "^2.0",
"workerman/crontab": "^1.0",
"kreait/firebase-php": "^7.2",
"zjkal/time-helper": "^1.1",
"tinywan/validate": "^0.0.6",
"ext-openssl": "*",
"yzh52521/webman-lock": "^1.0",
"ext-pdo": "*",
"yzh52521/webman-throttle": "^1.0",
"google/apiclient": "^2.13",
"symfony/translation": "^6.2",
"webman/redis-queue": "^1.2",
"vlucas/phpdotenv": "^5.5",
"webman/log": "^1.1"
}
運行偽代碼
// 增加硬幣,然后寫入訂單憑證
$call_info = $request->all();
$datedCoins = UserModel::getCacheUserInfo($call_info['user_id'], 'coins') ?? 0;
Log::error('開始事務(wù)');
Db::startTrans();
try {
$mysql_data = [
'user_id' => $call_info['user_id'],
'coins' => $call_info['reward_amount'],
'dated_coins' => $datedCoins,
'type' => 1,
];
// 將硬幣更新到用戶表,增加硬幣
Log::error('準備更新user表');
$result = (new UserModel())->where('user_id', '=', $call_info['user_id'])->cache(3600)->update(['coins' => ['inc', $call_info['coins']]]);
Log::error('user表更新成功');
if ($result){
// 寫入訂單表
Log::error('user表硬幣增加成功,開始寫入訂單表');
(new AdOrderModel())->create($mysql_data);
Log::error('訂單表寫入成功,準備提交事務(wù)');
Db::commit();
Log::error('事務(wù)提交成功');
return show('Success');
}else{
Db::rollback();
Log::error('coins增加失敗');
return show('fail');
}
} catch (DbException $e) {
Db::rollback();
Log::error('coins增加失敗');
} catch (\Exception $e) {
Db::rollback();
Log::error('coins增加失敗');
} finally {
Log::error('廣告硬幣增加成功--------------------');
}
打印請求流程,有異常前和沒有異常前都能正常執(zhí)行這個流程。
[2023-06-08 09:37:27][error]:開始事務(wù)
[2023-06-08 09:37:27][error]:準備更新user表
[2023-06-08 09:37:27][error]:user表更新成功
[2023-06-08 09:37:27][error]:user表硬幣增加成功,開始寫入訂單表
[2023-06-08 09:37:27][error]:訂單表寫入成功,準備提交事務(wù)
[2023-06-08 09:37:27][error]:事務(wù)提交成功
[2023-06-08 09:37:27][error]:返回成功
[2023-06-08 09:37:27][error]:廣告硬幣增加成功--------------------