Репликация MySQL и блокировки таблиц - PullRequest
2 голосов
/ 12 июня 2011

У меня следующая проблема.

У меня MMORPG-игра, основанная на PHP и MySQL, со средним числом запросов 600 в секунду.У меня случаются проблемы с таблицами, которые слишком долго заблокированы и задерживают другие запросы.(Например, запросы на обновление должны ждать запросов Select), и они должны ждать так долго, что память заполнена.

Эти запросы необходимы, и я не думаю, что смогу их больше оптимизировать.

Разумно ли использовать репликацию для Master-Slave?Мастер для записи и раб для выбора?Есть ли у ведомого устройства меньше проблем с выполнением операторов записи (из бункера), чем с ведущим?И действительно ли это поможет уменьшить количество проблем с блокировкой таблицы?

Заранее спасибо, Мартин


Хорошо, спасибо, что ответили.Так что, если я использую InnoDB для этих таблиц.Разумно ли смешивать их с MyISAM?

Поскольку тестовая таблица размером 70 МБ с MyISAM стала 200 МБ с InnoDB.Я предпочел бы иметь несколько таблиц, которые имеют проблемы с блокировками InnoDB, а другие только MyISAM.

Заранее спасибо, Мартин.

Ответы [ 2 ]

4 голосов
/ 13 июня 2011

Прежде чем думать о репликации и прочем, попробуйте следующее:

Я предполагаю, что ваши таблицы используют MyISAM.
MyISAM блокирует всю таблицу при выборе и заставляет обновление ждать, пока выбор не будет сделан.

Несколько идей, которые следует рассмотреть, прежде чем думать о репликации

Использование InnoDB
Переключите ваши столы на InnoDB.
InnoDB выполняет блокировку строк вместо блокировки таблиц. Только те строки, которые обновлены и выбраны, блокируются.

Рассмотрите возможность использования сводных таблиц
Если вы делаете много совокупных запросов, таких как:

select sum(score) from score where player_id = 1

Подумайте о создании таблицы memory следующим образом:

CREATE TABLE `test`.`totals` (
  `user_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `score` INTEGER UNSIGNED NOT NULL,
  other_fields .....
  PRIMARY KEY  USING HASH(`user_id`)
)
ENGINE = MEMORY;

Поставь триггер after update и after insert вот так:

DELIMITER $$

CREATE TRIGGER au_score_each AFTER UPDATE ON score FRO EACH ROW
BEGIN
  UPDATE totals SET score = score + (new.score - old.score) 
  WHERE totals.user_id = new.user_id;
END $$

DELIMITER ;

Теперь вы можете получать совокупные select запросы из таблицы totals, и вам больше не нужно увеличивать базу данных на полных таблицах.

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

Я не эксперт по репликации, поэтому я остановлюсь здесь, но я думаю, что вы прыгаете в master-slave, прежде чем исследовать альтернативы.

0 голосов
/ 14 июня 2011

Ведомые обновления являются однопоточными и просто повторяют обновления, которые были выполнены на ведущем устройстве. Таким образом, хотя вы можете получить небольшой скачок скорости от одного ведомого, вам действительно нужно иметь несколько ведомых, чтобы получить значительное увеличение скорости SELECT. Это значительно увеличит сложность вашей игры.

Если вы можете обновить сервер, то я бы рекомендовал сначала, а также взглянуть на настраиваемые параметры для MySQL, убедиться, что вы наилучшим образом используете доступную память и т. Д.

...