upsertの内部挙動について
Date2026/06/16 Last Modified2026/06/16
レコードの中で、auto incrementにしているカラムが不自然に増加してしまうという不具合があった。 原因について備忘録として残しておく。
upsert()を実行すると起こる事
Laravelの upsert()を実行すると、内部的にSQLでは以下のように変換される。
これは、INSERTを実行して特定のキーに重複があればUPDATEに切り替えるという便利な処理だが、 内部的にINSERTを実行してしまっているため、auto incrementが消費する。
そのため、日次バッチなどで「毎日同じデータを参照して変化があれば更新する」というような処理をかけていると、いざ新規のIDを発行したときに upsert()を実行した分だけIDが吹っ飛んでしまう。
解決策
upsert()を行わず、検索して条件分岐を組むべき。
検索したいキーをピックアップして →存在すれば update() →存在しなければ insert()
これで不用意なINSERTが実行されないので、auto incrementが消費されることはない。
補足
当初はMySQL/MariaDBにおけるupsertの不具合と思っていたが、書くにあたって調べたところPostgreSQLなどでも起こるそう。 なので、upsert()を使う場合はauto incrementが関与しないuuidなどのレコードに対して実行するようにしよう。