--> -->
#title(insertGetIdはスレッドセーフなのか?); * insertGetIdはスレッドセーフなのか? [#e736011e] DBにデータをinsertした後、Auto Incrementのフィールドに何が入ったかを知りたいケースがあります。そんな時に便利なのが、&inlinecode{insertGetId()};です。([[自動増分:https://readouble.com/laravel/5.4/ja/queries.html#inserts]])~ ~ ソースを見ると以下のように書かれており、insert後に[[PDO::lastInsertId:http://php.net/manual/ja/pdo.lastinsertid.php]]を実行して取得していることが分かります。~ #code(php){{{ public function processInsertGetId(Builder $query, $sql, $values, $sequence = null) { $query->getConnection()->insert($sql, $values); $id = $query->getConnection()->getPdo()->lastInsertId($sequence); return is_numeric($id) ? (int) $id : $id; } }}} ここで気になるのは、別クライアントから同時にアクセス(実行)され、insert(1) - insert(2) - lastInsertId(1) - lastInsertId(2) という順序で処理が走った場合、結果の整合性は補償されるのか? という点です。~ ~ そこで、以下のように検証してみました。~ ** テストコード [#sdd61fe7] 簡単なテスト用のテーブルを作って(下記ではlog用のテーブルを流用して)繰り返しinsertするコードを書きます。~ これは「php artisan command:test」で実行されるように書きました。 #code(php){{ for($cnt=0;$cnt<10;$cnt++){ $result = DB::table('logs')->insertGetId([適当な内容]); echo $result."\n"; } }} ** 呼び出すバッチファイル [#z9c5b0f7] test.bat #code(){{{ start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat start cmd /c sub.bat }}} ~ sub.bat #code(){{{ php artisan command:test pause }}} ** 検証 [#u67c9d02] 仮に上記のような順序で実行され、「lastInsertId(1) - lastInsertId(2)」のように連続でlastInsertId()が走るのであれば、同じ番号が返ってくるケースが生じることになります。~ test.batを実行すると10個のDOS窓が同時に開き、各々で同時並行的に10回ずつinsertが走ることになりますが、各窓に表示される数字が全て重複していなければ、概ね問題無いと考えられます。~ ~ 果たして結果は、全てuniqueな値が100個返ってきました。~ 中身はtransactionになってるんでしょうかね(ちゃんと読んでない・・・)。~