Проблема параллельных запросов в mysql - PullRequest
0 голосов
/ 28 июня 2009

Я сталкиваюсь со следующей проблемой

function book($memberid, $classid){
if (!book){
 // update the db and change the book variable to true
}
}

Моя проблема - 2 заявки, поданные одновременно. Первый запрос проходит строку, если (! Book) {но еще не обновляет БД. И в то же время второй запрос выполняет ту же функцию и также проходит строку if (! Book) {. Поэтому результат неверный.

Я хочу знать, как решить эту проблему параллелизма. Блокировка БД? Но я боюсь, что это повлияет на производительность.

Ответы [ 4 ]

1 голос
/ 28 июня 2009

Зачем вам нужна эта переменная?

Стандартный способ решения проблем параллелизма при обновлении баз данных состоит в том, чтобы позволить базе данных обрабатывать ее посредством транзакций (что в некоторых случаях влияет на производительность, но так же как и решение только с кодом).

Я бы хотел посмотреть, что входит в предложение if (! Book).

РЕДАКТИРОВАТЬ: Почему бы вам не изменить БД, чтобы сделать комбинацию (человек, класс) уникальным ключом? Таким образом, вы просто физически не можете вставить в таблицу дважды одно и то же значение. Я все еще беру дикие догадки, потому что это зависит от структуры базы данных. Также MySQL имеет специальный синтаксис для условной вставки, который здесь подходит. Проверьте это url .

0 голосов
/ 29 декабря 2018

В более общем смысле, если кто-то хочет защитить сегмент кода с помощью одновременного доступа, одним из способов является использование функций, предоставляемых библиотекой, которая поставляется вместе с компилятором, относительно лежащего в основе O.S.

В C / C ++ функции похожи на:

EnterCriticalSection ([Initialized]Section_ID);
< CODE_TO_PROTECT >
LeaveCriticalSection ([Initialized]Section_ID);

Но, возможно, в вашем случае для повышения эффективности вашей стратегии используйте следующую модификацию (если она доступна на вашем языке):

global: 
bool book = TRUE;

function book($memberid, $classid){
  while (!book); \\ this waits until the variable 'book' isn't TRUE
  // eventually, release the control of the task scheduler with:
  // while (!book) Sleep (1); 
  // performing a check every each millisecond.

  // then, first of all, set the variable to FALSE
  book = FALSE;

  // update the db
  ...
  ...

  // finally, set the variable 'book' again to TRUE...
  book = TRUE;
 }
0 голосов
/ 28 июня 2009

Можете ли вы использовать

UPDATE x SET y WHERE z

затем просто проверьте затронутые строки , чтобы увидеть, изменилось ли что-нибудь? Таким образом, MYSQL эффективно выполняет как проверку, так и фактическое изменение данных в одной плавной атомарной транзакции для вас без проблем с параллелизмом. (Я основываю это на том факте, что вы используете слово «обновить», а не «вставить» в своем вопросе; если это вставка, этот подход не будет работать, но VolkerK будет работать)

Если вам действительно нужно проверить с помощью SELECT, а затем написать с помощью UPDATE как 2 отдельных оператора, тогда транзакции - единственный путь. Вы упоминаете о блокировке БД - обратите внимание, что это не единственный доступный вариант. Если вы используете таблицы InnoDB, вы можете использовать много разных уровней.

0 голосов
/ 28 июня 2009

Если вы создаете уникальный индекс (человек, класс) , вы можете просто попытаться вставить новую запись без каких-либо предыдущих слов. Если уже есть другая запись с такими же значениями в (person, class), новая запись будет отклонена, и MySQL выдаст ошибку «дубликата ключа» , которая может быть надлежащим образом обработана вашим сценарием:

if ( 1062===mysql_errno() ) {
  echo "you've already made a reservation for this lecture.";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...