楽天市場ランキング取得で情報に不満足。原因は1213 Deadlockエラー
- 2020.04.14
- php備忘録
- 2ページ目以降, Deadlock, MySQL, PHP, transaction, ランキング取得, リアルタイムランキング, 楽天市場
楽天市場ランキング取得で情報に不満足。原因は1213 Deadlockエラー
ランキングの自動取得を作成しているわけですが、今までの1ページ目(楽天だったら35位)までの収集を拡張しようと思いスクリプトを修正しました。
そこで出会ったデッドロックエラー。
1 2 3 4 5 |
local.ERROR: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (SQL: delete from `jobs` where `id` = 18798) |
まぁね、1~35ページまでFORループで回して自社商品あったら書き込んでねとしていたので、書き込みのバッティングが生じたのだと思います。
と言う事で、この改善について。
ランキングの詳細(末番まで)が何故必要か
残念ながらすべての商品がカートジャンル1ページ目に来るわけではありません。
例えば『10個売れても200番台をうろつくジャンル』もありますし『1個売れれば5位に位置する商品』もあります。
私は「楽天市場は販売個数と販売額に楽天独自の係数をかけて順位を決めているのではないか」と推測しています。
「深くまでわかればランキング上位をとりやすいジャンルが分かるのではないか」そんな思いが『自社商品のランキング全部とって来いシステム』の原点です。
実際に取れた結果を見ると面白い
下は実際に自店舗にて得た結果です。
DailyRanking
- 134位 販売数:3000円×10個
- 14位 販売数:100円×10個
- 34位 販売数:4500円×2個
RealTimeRanking
- 49位 販売数:4000円×1個
- 5位 販売数:100円×20個
- 11位 販売数:100円×240個
こんな感じで振れ幅がデカい。
ジャンルだけではなく、リアルタイムランキングでは時間帯とかもあるので差異がありすぎて面白いですよね。
これの情報、取得量が少ないと何のデータにもなりませんが増えれば色々使えるんじゃね?と思うわけです。
われわれ店舗側の欲しい情報は『努力』の方向を決める指標
例えば、240個購入いただいてもリアルタイムランキングで1位を取れないジャンル。
デイリーランキング1位となればなおさら大変でしょう。
そこへ行くと、4500円×2個でデイリーランキング34位の商品は手を入れれば化けるかもしれません。
こういったどこに手を加えるかを判断する指標がEC用のツールには非常に少ないのが現実です。
無いんですよねホント…。となれば作るしかありません。
と、ここまでが作成するに至った理由です。
本題。エラーの改善について
発生したエラーはデッドロックエラーです。
こいつは、MYSQLへの書き込みがバッティングした際に発生します。
メンター曰く
JOBとは分身の術の事。
今回のスクリプト改修で大量のJOBを書き出す形にしたことで『沢山の分身』が生まれる事になった。
分身の術だから各自が各々勝手に動き回る事になる。
この弊害として、処理のバッティングが発生しているのが今現状。
この解決としては【 transaction 】という交通整備員を雇えば良い。
との事。
はい、transcation仕込んでみます。
transcationの書き方は2種類ある
その1:データ操作を自分でしっかり追いながら書く
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DB::beginTransaction(); try { $item = new Ranking(); $item->cart_id = $request->cart_id; $item->ranknumber = $request->ranknumber; $item->save(); // データ操作を確定させる DB::commit(); } catch(Exception $exception) { // データ操作を巻き戻す DB::rollBack(); throw $exception; } |
その2:フレームワークによろしくやってもらう
1 2 3 4 5 6 |
DB::transaction(function () use ($request) { $item = new Ranking(); $item ->cart_id= $request->cart_id; $item ->rankingnumber = $request->rankingnumber ; $item ->save(); }); |
うん、『その2』が楽です。
直してみたものの不穏な記事を発見
その後もいろいろ調べていたら不穏な記事を発見しました。
「databaseを使用してQueueを複数立ち上げると発生する」
そんなことがあるのか??
まぁ結論から言うと「書き方がしっかりしていればdatabaseでも大丈夫」と言う事で特に気にしなくてもいいみたいです。
まとめ
メンター的には細かいJOBを発行する仕様にデッカイ疑問がある様です。
大きなJOBを発行してその中でループ処理がベスト(セオリー)であるとの事。
でもなぁ~、やってみたら処理スピード上がるし、デッドロックエラーを回避できたらこの方法がいいんじゃないかなぁと思う今日この頃。
よくわからないけどね。
-
前の記事
2時間の処理が10分に。JOBはどう作ればよいか見直してみた。 2020.04.10
-
次の記事
ECコンサルをどこで評価するか、判断基準と使い道。 2020.04.14
コメントを残す