soulburner
@soulburner

MySQL — Синхронизация нескольких потоков

Имеется задача: вставить N элементов в таблицу, но перед этим удостовериться, не добавлены ли уже такие элементы.

Т.е. сначала делаем что-то вроде:

SELECT COUNT(*) FROM xxx WHERE x IN (x1,x2,x3,x4,x5,x6…… x1000);

Если результат равен 0, то значит можно делать такой же массовый INSERT.

Но есть проблема — как сделать это секурно при многопоточности?

Т.е., допустим, как избежать ситуации, когда одновременно получаются 2 потока и порядок действий получается таким:

П1: SELECT COUNT(*) — получает «0»
П2: SELECT COUNT(*) — получает «0»
П1: делает INSERT
П2: т.к. получил «ноль» в предыдущем селекте, тоже делает INSERT дублирующих записей

Есть ли решение для такой задачи?

Идея выставлять какой-то глобальный флаг кажется очень кривой и глупой.

Хранимки не предлагайте, т.к. опять-таки — они не спасут от одновременности. Как вообще такие вещи делаются?

Вставлять предполагается порой большие массивы данных по несколько десятков тысяч, так что вероятно, что запросы будут выполняться не слишком быстро и есть вероятность словить баг с одновременной вставкой.
  • Вопрос задан
  • 3611 просмотров
Пригласить эксперта
Ответы на вопрос 6
Транзакции, innodb.
Ответ написан
blo
@blo
инженер-программист
если x уникальное поле — то добавить UNIQUE KEY. и уточните какой у вас тип таблицы — myisam, innodb?
Ответ написан
apangin
@apangin
Простой вариант — LOCK TABLES, но лучше локами не злоупотреблять.
Ответ написан
LOCK TABLES ххх WRITE;
SELECT COUNT(*) FROM xxx WHERE x IN (x1,x2,x3,x4,x5,x6…… x1000);

INSERT INTO xxx ...;
UNLOCK TABLES;

Заблокирует таблицу для других сессий. Если в запросах между блокировкой и разблокировкой будут использоваться на чтение другие таблицы например WHERE x IN (SELECT * FROM xxx1), то их тоже надо, если не ошибаюсь блокировать: LOCK TABLES ххх WRITE, xxx1 READ
Ответ написан
Комментировать
mgyk
@mgyk
UNIQUE INDEX по полю и делайте INSERT IGNORE. Совпадающие поля отвалятся автоматом, такой вариант будет работать достаточно быстро.
Ответ написан
Комментировать
kashey
@kashey
Программирую большую половину жизни
INSERT ON DUPLICATE UPDATE и другие тригеры на вставку.
также — LOCK таблиц. Также лок мозгов на сервере и другие мьютексы.
Вариант 3 — работа через промежуточную инстацию
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы