Как намеренно заблокировать строку MySQL, чтобы даже SELECT возвращал ошибку?

Я пытаюсь использовать блокировку строк 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 ответа

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

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

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

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

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

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

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

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

например

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

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

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

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

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

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

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

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

Другие вопросы по тегам