Блокировка чтения и записи MySQL

#mysql #locking

Вопрос:

Я бы хотел, чтобы клиентский сеанс заблокировал таблицу, чтобы она могла продолжать чтение и запись в эту таблицу. В то же время другие клиентские сеансы должны иметь возможность считывать данные только из таблицы. Как только блокировка будет снята, всем клиентским сеансам должно быть разрешено чтение из таблицы и запись в нее. Кроме того, как только блокировка будет снята, все клиентские сеансы, которые пытались выполнить запись в таблицу, пока она была заблокирована, должны быть выполнены. Я не хочу, чтобы при попытке вставки во время блокировки возникали какие-либо ошибки.

Я знаю, что блокировка чтения не сработает, потому что клиентский сеанс, создающий блокировку, не может записывать данные в таблицу, пока блокировка существует. Кроме того, блокировка записи не будет работать, потому что другие клиентские сеансы не могут считывать данные из таблицы. Есть ли у меня какой-нибудь способ сделать это?

Комментарии:

1. Блокировка таблиц редко является правильным решением. Блокировки записи обычно означают эксклюзивные блокировки, то есть только данное соединение может получить доступ к таблице. В этом случае вам, возможно, придется реализовать блокировку на уровне приложения.

2. Вы недостаточно объяснили, почему этого стандарта BEGIN; ((do read FOR UPDATE ... writes)) COMMIT; недостаточно. Обратите внимание на FOR UPDATE .

3. @RickJames BEGIN; ((do read FOR UPDATE ... writes)) COMMIT; кажется хорошим решением, пока другие клиенты могут продолжать читать из таблицы. По словам Билла, похоже, что они могут это сделать.

Ответ №1:

Вы не можете сделать это с блокировками таблиц, используя LOCK TABLES оператор, по причинам, указанным в вашем вопросе.

Вы можете сделать это, создав блокировки строк во всех строках таблицы:

 SELECT COUNT(*) FROM mytable FOR UPDATE;
 

Блокировки строк блокировали бы запись любых других сеансов до тех пор, пока вы не зафиксируете транзакцию, но они могли бы читать, если только они не пытаются использовать блокировку запросов на чтение. Тем временем вы можете прочитать или записать таблицу, так как у вас уже есть блокировки на всех строках.

Другое решение-получить глобальную блокировку, но не использовать LOCK TABLES ее . Я закодировал системы, в которых все участвующие клиенты должны получить блокировку с помощью функции GET_LOCK() перед записью в таблицу. Но если им нужно только прочитать, они просто пропускают запрос на эту блокировку. Это сработало бы, но для этого потребовалось бы, чтобы все клиенты включали код для поддержки одной и той же политики доступа.

Комментарии:

1. BEGIN; SELECT COUNT(*) FROM mytable FOR UPDATE; COMMIT; похоже, это может быть то, что я ищу, так как другие клиенты все еще могут читать из таблицы.