Тупик MySQL при использовании SELECT FOR UPDATE SKIP LOCKED? Нужна помощь (очень подробный вопрос)Php

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Тупик MySQL при использовании SELECT FOR UPDATE SKIP LOCKED? Нужна помощь (очень подробный вопрос)

Сообщение Anonymous »

У меня есть система очередей, построенная с использованием PHP и MySQL (изначально я создал ее с помощью Redis, но она была довольно сложной и не очень гибкой), и после некоторых исследований я обнаружил, что начиная с MySQL 8.0.1 существует новый аргумент, который позволил (эффективно? и надежно?) строить очереди с помощью MySQL, и этот новый аргумент FOR UPDATE SKIP LOCKED, который, судя по тому, что я прочитал, должен предотвращать взаимоблокировки, некоторые ссылки ref 1, ссылка 2, ссылка 3.
В моей текущей реализации у меня есть две таблицы, называемые QueueJobsPending и QueueJobsProcessed, как следует из их названий, первая из них находится только в ожидании задания, а другой содержит обработанные (как неудачные, так и успешные), таблицы следующие:

Код: Выделить всё

CREATE TABLE QueueJobsPending (
id CHAR(15) BINARY UNIQUE NOT NULL, PRIMARY KEY (id),
jobKey VARCHAR(255) NOT NULL,
jobState ENUM('Pending', 'Processing') NOT NULL,
queueName VARCHAR(255) NOT NULL,
params JSON NOT NULL,
tags JSON NOT NULL,
maxExecutionTime INTEGER NOT NULL,
maxReleases INTEGER NOT NULL,
releasesCounter INTEGER NOT NULL,
maxRetries INTEGER NOT NULL,
retriesCounter INTEGER NOT NULL,
executeAfterTimestamp INTEGER UNSIGNED NOT NULL,
createdAt TIMESTAMP NOT NULL,
updatedAt TIMESTAMP NULL,
sequence BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, KEY sequence (sequence)
);

CREATE INDEX index_jobKey ON QueueJobsPending(jobKey);
CREATE INDEX index_jobState ON QueueJobsPending(jobState);
CREATE INDEX index_queueName ON QueueJobsPending(queueName);
CREATE INDEX index_executeAfterTimestamp ON QueueJobsPending(executeAfterTimestamp);

Код: Выделить всё

CREATE TABLE QueueJobsProcessed (
id CHAR(15) BINARY UNIQUE NOT NULL, PRIMARY KEY (id),
pendingQueueJobId CHAR(15) BINARY UNIQUE NOT NULL, -- ONLY FOR THE PURPOSES OF ENSURING A PENDING JOB IS NOT PROCESSED TWICE
jobKey VARCHAR(255) NOT NULL,
jobState ENUM('Completed','Failed') NOT NULL,
queueName VARCHAR(255) NOT NULL,
params JSON NOT NULL,
tags JSON NOT NULL,
errors JSON NOT NULL,
maxExecutionTime INTEGER NOT NULL,
maxReleases INTEGER NOT NULL,
releasesCounter INTEGER NOT NULL,
maxRetries INTEGER NOT NULL,
retriesCounter INTEGER NOT NULL,
executeAfterTimestamp INTEGER UNSIGNED NOT NULL,
createdAt TIMESTAMP NOT NULL,
sequence BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, KEY sequence (sequence)
);

CREATE INDEX index_jobKey ON QueueJobsProcessed(jobKey);
CREATE INDEX index_jobState ON QueueJobsProcessed(jobState);
CREATE INDEX index_queueName ON QueueJobsProcessed(queueName);
И при получении следующего задания для обработки я запускаю следующие два запроса внутри транзакции.

Код: Выделить всё

SELECT *
FROM QueueJobsPending
WHERE
jobState = 'Pending'
AND executeAfterTimestamp pendingQueueJobHydrator->getTableColumnsForSelect();
$now = $this->clock->now(TimeZoneEnum::UTC)->toTimestamp();

$queueNames = array_map(fn (string $queueName) => $this->quote($queueName), $queueNames);
$queueNamesStr = implode(',', $queueNames);

$pendingStateStr = PendingQueueJobStateEnum::Pending->value;

try {
$this->beginTransaction();

$query = "
SELECT {$pendingQueueJobColumns}
FROM QueueJobsPending
WHERE
jobState = '{$pendingStateStr}'
AND executeAfterTimestamp 

Подробнее здесь: [url]https://stackoverflow.com/questions/79241232/mysql-deadlock-when-using-select-for-update-skip-locked-need-help-very-detaile[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»