#mysql #replication
#mysql #репликация
Вопрос:
У меня следующая проблема.
У меня есть MMORPG-игра, основанная на PHP и MySQL, в которой сейчас в среднем выполняется около 600 запросов в секунду. У меня возникли проблемы с таблицами, которые заблокированы слишком долго и задерживают другие запросы. (Запросы на обновление, например, должны ждать запросов на выбор) и им приходится ждать так долго, что память заполняется.
Эти запросы необходимы, и я не думаю, что смогу их больше оптимизировать.
Разумно ли использовать репликацию для Master-Slave? Ведущий для записи и подчиненный для выбора? У ведомого устройства меньше проблем с производительностью при использовании инструкций write (из лог-бина), чем у ведущего? И действительно ли это поможет устранить меньше проблем с блокировкой таблиц?
Заранее спасибо, Мартин
А, ладно, спасибо за ответ. Итак, если я использую InnoDB для этих таблиц. Разумно ли смешивать их с MyISAM?
Потому что тестовая таблица, которая была 70 МБ с MyISAM, стала 200 МБ с InnoDB. Я бы предпочел, чтобы у некоторых таблиц были проблемы с блокировками таблиц InnoDB, а у других — только MyISAM.
Заранее спасибо, Мартин.
Комментарии:
1. Мартин, добро пожаловать в stackoverflow.
2. Я объединил ваши две незарегистрированные учетные записи. Теперь вы можете редактировать свой вопрос и оставлять комментарии под отдельными ответами.
Ответ №1:
Прежде чем вы подумаете о репликации и прочем, попробуйте это:
Я предполагаю, что ваши таблицы используют 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
таблицы, и вам больше не нужно использовать базу данных для полных таблиц.
Несколько замечаний о master-slave
Обратите внимание, что master slave в MySQL является асинхронным. Это означает, что если вы выберете из подчиненного устройства и обновите на главном, ваши подчиненные данные будут отставать.
Это означает, что вы обмениваете свои проблемы с блокировкой на проблемы с задержкой по времени.
В игре с большим количеством очков это может быть проблемой.
Кроме того, вы усложняете свою настройку.
Я не эксперт по репликации, поэтому я остановлюсь здесь, но я думаю, что вы переходите к master-slave, прежде чем изучать альтернативы.
Ответ №2:
Подчиненные обновления являются однопоточными и просто повторяют обновления, которые были выполнены на главном сервере. Таким образом, хотя вы можете получить небольшое увеличение скорости от одного подчиненного устройства, вам действительно нужно иметь несколько подчиненных устройств, чтобы получить значительное увеличение скорости ВЫБОРА. Это значительно увеличило бы сложность вашей игры.
Если вы можете обновить свой сервер, я бы рекомендовал сначала также взглянуть на настраиваемые параметры для MySQL, убедиться, что вы наилучшим образом используете доступную память и т.д.
Комментарии:
1. Ах, ладно, я сомневаюсь, что моя система может обрабатывать несколько подчиненных устройств. :S Теперь я рассмотрю использование InnoDB, как предлагается ниже. (спасибо, Йохан!) Спасибо вам обоим за ответ!