Есть ли более эффективный метод, чем транзакции? - PullRequest
3 голосов
/ 26 января 2010
insert into table1 ...;
update table2 set count=count+1;

Вышеуказанное вставляет что-то в table1, и, если это удается, обновляет поле count table2.

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

Каково ваше решение?

Я использую PHP и выполняю транзакции следующим образом:

mysql_query('begin');

mysql_query($statement1);

mysql_query($statement2);
...
mysql_query('commit');

То есть все таблицы, указанные в этих $statement, будут заблокированы?

Ответы [ 6 ]

3 голосов
/ 26 января 2010

Транзакция (которая в контексте MySQL предполагает InnoDB) не должна блокировать всю таблицу.

INSERT заблокирует отдельный ряд без блокировок пробела.

UPDATE также не будет блокировать пробелы, если вы предоставите условие равенства или IN для индексированного поля в предложении WHERE.

Это означает, что при правильно проиндексированной таблице INSERTs не будет блокировать друг друга, тогда как UPDATEs будет блокировать друг друга только в том случае, если они влияют на одну и ту же строку.

UPDATE, конечно, заблокирует отдельную строку, на которую он влияет, но, поскольку это последняя операция в вашей транзакции, блокировка будет снята сразу после ее совершения.

Фактически требуется сама блокировка, чтобы два одновременных обновления увеличивали число последовательно.

2 голосов
/ 26 января 2010

Транзакции не обязательно запрашивают блокировку для всей таблицы.

Кроме того, InnoDB поддерживает различные уровни изоляции перевода, используя разные стратегии блокировки. Вы можете проверить:

2 голосов
/ 26 января 2010

Использовать механизм хранения InnoDB. Это блокировка на уровне строки вместо MyISAM, которая является блокировкой на уровне таблицы.

1 голос
/ 26 января 2010

Транзакции прекрасно подходят для обеспечения поведения «все или ничего» - даже если в вашей системе высокая нагрузка или высокий параллелизм, вам не следует прекращать использовать транзакции, по крайней мере, если вам нужны ваши данные, чтобы оставаться согласованными!

(И транзакции не обязательно блокируют всю таблицу)

1 голос
/ 26 января 2010

для меня это больше похоже на работу «Триггеров». onInsert сделать что-то.

0 голосов
/ 26 января 2010

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

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

...