Как намеренно заблокировать строку MySQL, чтобы даже SELECT возвращал ошибку? - PullRequest
8 голосов
/ 12 января 2010

Я пытаюсь использовать блокировку строк MySQL, чтобы эмулировать MuteEx для строки. Допустим, в моей таблице 2 столбца, идентификатор и текстовое поле, а также три записи (1, a) (2, b) и (3, c). SELECT * FROM table; вернул бы эти результаты. Я могу заблокировать определенную строку обычным способом.

START TRANSACTION;
BEGIN;
SELECT * FROM table WHERE id = '2' FOR UPDATE;

Однако, если со второго соединения я должен был выбрать * из таблицы. Это вернуло бы все 3 результата. Есть ли способ для блокировки на уровне строк, чтобы в принципе запретить любому SELECT видеть / использовать заблокированную строку? По сути, я пытаюсь помешать кому-либо использовать строку, которая в настоящее время используется / манипулируется, или даже просматривать строку как ее данные (поскольку она используется / манипулируется), и нельзя доверять ее точности во время SELECT .

Ответы [ 4 ]

5 голосов
/ 22 февраля 2011

Вам нужен LOCK IN SHARE MODE.Использование его с SELECT гарантирует, что никто не блокирует строки с FOR UPDATE.

, например,

Клиент A делает SELECT * FROM table WHERE type=2 FOR UPDATE

Клиент B делает SELECT * FROM table LOCK IN SHARE MODE и зависаетздесь

Клиент A пишет / INSERTs / UPDATE что-то, а затем выполняет COMMIT

Клиент B теперь размораживается и возобновляет обработку

5 голосов
/ 12 января 2010

Если вы установите уровень изоляции транзакции на SERIALIZABLE, InnoDB, то будет добавлено LOCK IN SHARE MODE ко всем SELECT операторам.

Этот режим конфликтует с блокировками, установленными SELECT FOR UPDATE, и SELECT s блокируется.

Обратите внимание, что InnoDB может заблокировать больше строк, чем удовлетворяет условию WHERE. Это потому, что он блокирует все строки отсканированные , а не только те строки, которые соответствовали .

Скажем, у вас есть индекс на col1 и этот запрос:

SELECT  *
FROM    mytable
WHERE   col1 = 1
        AND col2 = 2
FOR UPDATE

использует этот индекс.

Это заблокирует все записи с col1 = 1, даже те, с col2 <> 2

2 голосов
/ 12 января 2010

На самом деле, данные строки можно доверять, даже когда вы ими манипулируете.

Если вы начнете транзакцию с одного соединения, другие соединения не увидят никаких ваших изменений, пока вы не совершите транзакцию.

0 голосов
/ 12 января 2010

Я не знаю, существует ли собственный, блокирующий специальный механизм, чтобы сделать это, но мой первый инстинкт должен был бы дать таблице столбец статуса (например, locked) и установить его в 1 при блокировке строка. select, чувствительное к этому, будет всегда добавлять условие WHERE locked != '1' к любому запросу.

С другой стороны, я не знаю, что вы делаете, но разве это не задача, которая должна выполняться на один или два уровня выше ядра базы данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...