Предотвращение взаимных блокировок mysql в вашем php-приложении, которое использует SELECT ... LOCK IN SHARE MODE - PullRequest
1 голос
/ 17 октября 2011

Stack:

Если я правильно понимаю SELECT ... LOCK IN SHARE MODE, вы можете поместить его в транзакцию mysql, чтобы выбрать строки, с которыми вы будете работать во время этой транзакции, чтобы "заблокировать"«эти выбранные строки из действий по записи / удалению другого сеанса (но другие сеансы все еще могут читать строки) до тех пор, пока ваша транзакция не завершится, и в этот момент строки, заблокированные с помощью инструкции SELECT LOCK IN SHARE MODE, освобождаются, чтобы другие сеансы могли получить к ним доступ.для записи / удаления и т. д.

Это именно то, что я хочу для моей таблицы комментариев.Каждый раз, когда комментарий добавляется в сообщение на моем сайте, мне нужно заблокировать все строки комментариев, связанные с этим сообщением, в то время как я обновляю некоторые метаданные по всем заблокированным строкам.И если два комментария будут отправлены одновременно, я не хочу, чтобы они оба имели доступ к соответствующим строкам комментариев в одно и то же время, потому что они в основном испортят друг друга (и метаданные).Поэтому я хочу включить SELECT LOCK IN SHARE MODE в скрипт загрузки комментариев, чтобы первый сеанс, выполняющий блокировку в запросе, получил полный контроль над строками комментариев, пока не завершит всю транзакцию (и сценарий, который был немного медленнее, должен ждать, покався транзакция из первого сценария выполняется).

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

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

1 Ответ

0 голосов
/ 22 июня 2012

В документации по MySQL, страница 14.6.8.1. Режимы блокировки InnoDB обсуждают (в нижней части страницы) ситуацию взаимоблокировки, вызванную первым клиентом, запрашивающим блокировку чтения с помощью «LOCK IN SHARE MODE», и вторым клиентом, запрашивающим блокировку записи из-за удаления. Второй клиент блокируется блокировкой чтения первого клиента, поэтому его блокировка записи ставится в очередь. Но когда первый клиент пытается удалить, происходит следующее:

Здесь возникает тупик, потому что клиент A нуждается в X (эксклюзивной) блокировке для удаления строка. Однако этот запрос блокировки не может быть предоставлен, потому что клиент B уже есть запрос на блокировку X и ожидает клиента A для освободить свою S (общую) блокировку. Также S замок, удерживаемый А, не может быть повышен до Х блокировка из-за предварительного запроса B на блокировку X. В следствии, InnoDB генерирует ошибку для клиента A и снимает его блокировки. При этом точка, запрос блокировки для клиента B может быть удовлетворен, и B удаляет строка из таблицы.

Если я правильно понимаю, я думаю, что проблема может быть решена первым клиентом, использующим ДЛЯ ОБНОВЛЕНИЯ вместо "LOCK IN SHARE MODE". Это приводит к тому, что первый клиент получает блокировку записи с самого начала, а затем он никогда не должен ждать второго клиента.

Используйте транзакцию вокруг операторов запроса и обновления, и блокировка будет удерживаться до тех пор, пока вы не совершите транзакцию. Никаких других блокировок таблицы не требуется.

...