See if this helps: https://laracasts.com/discuss/channels/laravel/serialization-failure-1213-deadlock-found-when-trying-to-get-lock-try-restarting-transaction
And
And look at retries here https://laravel.com/docs/11.x/database#handling-deadlocks
Hi!
See in my laravel log, this error:
2024-09-27 08:02:39] production.ERROR: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (Connection: mysql, SQL: delete from `unprocessed_gps_data` where `id` in (706698, 706699, 706700, 706701, 706702, 706703, 706704, 706705, 706706)) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 40001): SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (Connection: mysql, SQL: delete from `unprocessed_gps_data` where `id` in (706698, 706699, 706700, 706701, 706702, 706703, 706704, 706705, 706706.....
Here is my command in laravel, that gives me this error
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\UnprocessedGpsData;
use App\Models\TrackerGps;
use App\Facades\GpsService;
use App\Models\Golfclub;
use Illuminate\Database\Eloquent\Collection;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class ProcessGpsDataCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'easyflow:process-gps-data';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Process GPS data';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// Process data twice in one minute, with a 30-second delay between runs
$chunkSize = 500; // Process data in chunks of 500 records
UnprocessedGpsData::where('status', 0)->chunk($chunkSize, function ($unprocessedData) {
$idsToUpdate = [];
$idsToDelete = [];
//test
DB::transaction(function () use ($unprocessedData, &$idsToUpdate, &$idsToDelete) {
// Fetch trackers in bulk to avoid repeated querying
$trackers = TrackerGps::whereIn('tracker', $unprocessedData->pluck('tracker'))->get()->keyBy('tracker');
foreach ($unprocessedData as $unprocessed) {
$tracker = $trackers->get($unprocessed->tracker);
// If no tracker found, create a new one
if (!$tracker) {
$tracker = new TrackerGps();
$tracker->tracker = $unprocessed->tracker;
$tracker->golfclub_id = config('tracker.default_club');
}
// Update tracker's battery value
$tracker->battery = $unprocessed->battery;
$tracker->updated_at = Carbon::now();
$tracker->save();
// Store GPS position and process it
$isProcessed = GpsService::storegpsposWithCoordinates(
null,
$tracker,
$unprocessed->latitude,
$unprocessed->longitude,
$unprocessed->date,
0.0, // Assuming altitude as 0.0
1 // Assuming some default status
);
// Mark as processed
$unprocessed->status = 1;
$unprocessed->save();
if ($isProcessed === false) {
$idsToUpdate[] = $unprocessed->id; // Data that failed to process
} else {
$idsToDelete[] = $unprocessed->id; // Successfully processed data
}
}
// Delete successfully processed data
if (!empty($idsToDelete)) {
UnprocessedGpsData::whereIn('id', $idsToDelete)->forceDelete();
}
if (!empty($idsToUpdate)) {
UnprocessedGpsData::whereIn('id', $idsToUpdate)->forceDelete();
}
});
});
return "Done";
}
}
Deadlock must be problem with:
if (!empty($idsToDelete)) {
UnprocessedGpsData::whereIn('id', $idsToDelete)->forceDelete();
}
if (!empty($idsToUpdate)) {
UnprocessedGpsData::whereIn('id', $idsToUpdate)->forceDelete();
}
What is the issue here ?
My guess is that you start the transaction, but you never end it.
A bit simplified, but a transaction works like this.
There are two ways to release the record for others to update, commit and rollback, one of these must be ran after a select for update is performed.
So if one session does
SELECT * FROM table1 FOR UPDATE;
Nobody else can do anything other than a plain select on any of the records in the table.
It is very important not to select and lock more records than you should work with, and they should be released as soon as possible.
Please or to participate in this conversation.