Xpoint
   [напомнить пароль]

Необходимость локирования базы и таблиц MySQL

Метки: [без меток]
[удл]
2011-01-28 10:32:04 [обр] neokoder[досье]

Надо ли обязательно перед выполнением SQL-запроса на запись в таблицу, который могут одновременно вызвать несколько пользователей сайта локировать эту таблицу или всю базу данных. Или же php и MySQL сами автоматически могут разруливать одновременные обращения нескольких пользователей сайта.

Какие вообще стандарты существуют на этот счёт?

Вот к примеру есть php-скрипт, который вносит изменения в таблицу posts. Т.е. много пользователей могут добавлять своё сообщение в тему почти одновременно. Будут ли конфликты одновременного доступа к БД или даже одновременного вызова php-скрипта или нет? Нужно что-то дополнительно предусматривать?

спустя 9 минут [обр] Евгений Седов aka KPbIC(0/187)[досье]
М Перенесено из форума "Программирование::PHP"
спустя 2 часа 25 минут [обр] Евгений Седов aka KPbIC(0/187)[досье]
Не будет конфликтов. Это одна из причин, по которой люди используют базы данных.
спустя 19 минут [обр] neokoder[досье]

Т.е. есть у меня 10 пользователей одновременно записывают новую строчку в одну таблицу, то хотите сказать конфликтов не будет? СУБД MySql и PHP сами автоматически это проконтролируют. Так?

Не надо дополнительно использовать LOCK?

спустя 2 минуты [обр] Евгений Седов aka KPbIC(0/187)[досье]
Приведите конкретный пример. Покажите структуру таблицы, запрос и опишите логику этого куска приложения.
спустя 28 минут [обр] neokoder[досье]
Я только планирую работать через PHP с MySQL, поэтому и спрашиваю как мне писать скрипт. Нужно использовать LOCK перед запрсом или же не надо заморачиваться и по умолчанию MySQL сам будет локировать таблицы если одновременно несколько пользователей будут вызывать скрипт.
спустя 9 минут [обр] Евгений Седов aka KPbIC(0/187)[досье]
Не нужно ничего лочить.
спустя 55 минут [обр] neokoder[досье]
Ну вы же просили меня привести структуру таблиц и запрос. Значит всё же для чего то локирование необходимо делать. Можете объяснить в каких случаях локирование будет требоваться?
спустя 27 минут [обр] Евгений Седов aka KPbIC(0/187)[досье]

Когда вам недостаточно тех блокировок, которые автоматически создаются самой базой.

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

спустя 2 часа 38 минут [обр] Thirteensmay(0/157)[досье]
Необходимо различать физические и логические ошибки, физические это когда может возникнуть косяк с одновременной записью, добавлением, изменением, удалением записи, такие ошибки база обходит самостоятельно, не надо ничего лочить, можете писать как угодно, ошибок не возникнет. Логические же ошибки возможны, например типа описанной Евгений Седов aka KPbIC[досье], возможны и др, их необходимо учитывать самостоятельно, и тут есть различные варианты. Во первых это атомарные запросы, т.е. вместо двух, чтение и потом запись, вы можете выполнить один INSERT INTO SELECT FROM, в момент выполнения одного запроса база гарантирует свою неизменность. Во вторых существует понятие транзакций, в третьих - блокировки. Транзакции это более высокоуровневое понятие, самостоятельно использующее в своей работе блокировки, и обеспечивающее дополнительные вкусности типа автоматического отката изменений в случае необходимости, гарантии целостной записи группы действий и т.п. Хорошо построенная пользователем база как правило не требует явного вызова блокировок. MySQL поддерживает транзакции для таблиц типа InnoDB, таблицы MyISAM транзакций не поддерживают, в этом случае остается использовать только блокировки, в крайнем случае, т.к. тормозят. По любому почитайте про транзакции.
спустя 23 часа [обр] neokoder[досье]
Спасибо, понятно.
Про транзакции почитаю.
спустя 21 минуту [обр] Евгений Седов aka KPbIC(0/187)[досье]
сообщение промодерировано
Учтите, что в приведенном мною раньше случае транзакция не поможет. Но я согласен с Thirteensmay[досье], если вам потребовался явный LOCK, то стоит поискать проблемы в структуре таблиц.
спустя 8 часов [обр] Thirteensmay(0/157)[досье]
Учтите, что Евгений мог погорячиться, его пример решается с помощью установки уровня изолированности транзакции Serializable, во взрослых СУБД, также, вместо явных локов гораздо лучше применять атомарные запросы либо в общем случае конструкцию select for update которая установит оптимальный лок автоматически.
спустя 8 часов [обр] Евгений Седов aka KPbIC(0/187)[досье]
сообщение промодерировано

Thirteensmay[досье]

select for update залочит только выбранные записи, но не всю таблицу.

Вам не кажется, что дальнейшее углубление в тему только запутает автора? Он, ведь, еще только собирается использовать базу.

спустя 2 часа 48 минут [обр] Thirteensmay(0/157)[досье]
Конечно, тут много моментов, но я думаю у нас в принципе неплохо получилось, кратко и последовательно, начиная с азов и до некоторых конкретных конструкций, автор хотел знать вообще, надеюсь он получил хороший стартовый обзор, дальше можно читать самостоятельно, согласен с тем что дальнейшее углубление может запутать.
спустя 2 часа 9 минут [обр] neokoder[досье]

Неа, не запутали. Наоборот спасибо вам за разъяснения.
Я понял главное:
Если использовать атомарные запросы, то ничего дополнительно лочить не надо. СУБД MySQL и PHP сами разруливают многопотоковый и многопроцессорный доступ к данным базы.

Если мне необходимо выполнить несколько запросов в одном php-скрипте, т.е. необходима модификация нескольких таблиц, тогда необходимо использовать транзакции(использующие блокировку автоматически и снимающие при необходимости текущую блокировку БД, если она установлена) или блокировку строк, или всей таблицы, в зависимости от того какие данные я использую. Это необходимо для того, чтобы быть уверенным в неизменности таблиц. Пока мой запрос находится в промежуточной стадии(не выполнен до конца), другой пользователь сайта может изменить данные, которые я использую в запросах.

Если где ошибся, поправьте.

спустя 1 час 7 минут [обр] Thirteensmay(0/157)[досье]

Трудно сказать ошиблись вы или нет, смотря что вы подразумеваете под этими словами, ошиблись как минимум в последнем предложении, возможно просто были невнимательны. Пока один запрос выполняется для него автоматически гарантируется что база неизменна, даже если параллельно происходят другие запросы, в этом и есть смысл атомарности одного запроса, а вот если под словом запрос вы подразумевали последовательность нескольких атомарных запросов, то все более менее верно, между запросами база может измениться, и если ваша последовательность зависит от этого, но не учитывает, то возможна логическая ошибка.

Простейший пример, первым запросом вы выбираете некоторые данные из таблицы, а потом другими запросами начинаете изменять базу, в расчете на те данные что получили первым запросом, но в базе эти данные уже могли измениться, запросами от других пользователей, и может получится ошибка т.к. вы будете оперировать устаревшими данными, поэтому вам как то надо заблокировать эти данные первым запросом. Блокировать можно разными способами, для этого существуют явные блокировки, транзакции с разными уровнями изолированности и специальные конструкции типа select for update, зависит от конкретного случая. Нужно стремиться не заблокировать лишних данных. К тому же надо учитывать что блокировки могут быть разными, блокировки на чтение и на запись, сама база зачастую использует блокировки только на запись, т.е. заблокированные данные можно прочитать, что в последствии может вызвать проблемы.

спустя 28 минут [обр] Thirteensmay(0/157)[досье]

Вот здесь по моему хорошо описано, что касается конкретно MySQL http://webew.ru/articles/1383.webew

На самом деле вопрос блокировок достаточно сложен, если стремиться не блокировать лишних данных. Вам же для начала думаю вполне достаточно будет в начале работы выполнять lock tables mytable write, а в конце unlock tables, это конечно достаточно жестко, зачастую черезчур, и скорее всего будет приводить к падению производительности, т.к. остальные будут всегда ждать, но для начала вполне, далее вы можете разобраться с вопросом более подробно и начать использовать более бережные блокировки.

спустя 19 часов [обр] neokoder[досье]
Простейший пример, первым запросом вы выбираете некоторые данные из таблицы, а потом другими запросами начинаете изменять базу, в расчете на те данные что получили первым запросом, но в базе эти данные уже могли измениться, запросами от других пользователей, и может получится ошибка т.к. вы будете оперировать устаревшими данными, поэтому вам как то надо заблокировать эти данные первым запросом.
Именно это я и имел в виду. Ещё раз спасибо.
Powered by POEM™ Engine Copyright © 2002-2005