Тяжелая запись в кластер Galera - таблица заблокирована, кластер практически непригоден
Я установил Galera Cluster на 3 узла. Он отлично работает для чтения данных. Я сделал простое приложение, чтобы сделать некоторые тесты на кластере. К сожалению, я должен сказать, что кластер терпит неудачу полностью, когда я пытаюсь сделать некоторую запись. Может быть, он может быть настроен по-другому, или я делаю что-то неправильно?
У меня есть простая хранимая процедура:
CREATE PROCEDURE testproc(IN p_idWorker INTEGER)
BEGIN
DECLARE t_id INT DEFAULT -1;
DECLARE t_counter INT ;
UPDATE test SET idWorker = p_idWorker WHERE counter = 0 AND idWorker IS NULL limit 1;
SELECT id FROM test WHERE idWorker = p_idWorker LIMIT 1 INTO t_id;
SELECT ABS(MAX(counter)/MIN(counter)) FROM TEST INTO t_counter;
SELECT COUNT(*) FROM test WHERE counter = 0 INTO t_counter;
IF t_id >= 0 THEN
UPDATE test SET counter = counter + 1 WHERE id = t_id;
UPDATE test SET idWorker = NULL WHERE id = t_id;
SELECT t_counter AS res;
ELSE
SELECT 'end' AS res;
END IF;
END $$
Теперь мое простое приложение на C# создает, например, 3 клиента MySQL в отдельных потоках, и каждый из них выполняет процедуру каждые 100 мс, пока не будет записи, где столбец counter = 0.
К сожалению - примерно через 10 секунд что-то идет плохо. На серверах существует процесс query_end, который никогда не заканчивается. После этого - вы не можете обновить таблицу тестов, MySQL возвращает:
ОШИБКА 1205 (HY000): превышено время ожидания блокировки; попробуйте перезапустить транзакцию
, Вы не можете даже перезапустить MySQL. Что вы можете сделать, это перезагрузить сервер, иногда весь кластер. Является ли Galera Cluster ненадежным, когда вы выполняете массовые параллельные записи / обновления? Сложно поверить.
2 ответа
У нас была почти та же проблема - когда мы обновляли, это не удавалось с таймаутом блокировки. Наша текущая стратегия состоит в том, чтобы использовать один сервер для фоновых процессов и массовых записей, а два других сервера использовать для живых веб-серверов.
Это довольно легко, если вы используете HAProxy - но нам также пришлось внести некоторые изменения в наш код.
Пока что кажется, что он работает намного лучше, но мы определенно увидим, работает ли он хорошо через несколько недель (когда мы не столкнемся с теми же проблемами, что и у нас).
Некоторые заметки из нашего опыта:
Несколько недель спустя я могу сказать, что изменения действительно имели большое значение. Я думаю, что наиболее важным изменением было проанализировать фоновые процессы и запланировать их, чтобы они не перекрывались (или не перекрывались так сильно).
Смена сервера, так что только один сервер в основном используется для записи, а два других сервера используются для чтения, что улучшило наш пользовательский опыт во время тяжелых фоновых процессов.
Третий шаг, который мы сделали, - улучшить фоновые процессы. Во время одной транзакции программист бросил таблицу и восстановил ее с нуля. Мы изменили это, чтобы сначала проверить, нужно ли изменение, а затем обновить строку. Это значительно улучшило производительность этого процесса.
Наш опыт показывает, что чтение очень быстро в кластере Galera, но запись может быть довольно медленной, особенно если вы выполняете тонны операций записи. Вначале у нас были некоторые ошибки, и нам пришлось заново импортировать всю таблицу - это сильно повредило базе данных. Еще одна вещь, которая дважды разбила наш сервер, заключалась в том, что бинлог заполнил диски сервера, который разбил сервер. Также обязательно измените все базы данных на таблицы Innodb, иначе возможна потеря данных. Один из наших программистов установил все таблицы журналов в MyISAM - скажем, мы потеряли некоторые из наших журналов в этом процессе.
Но, в конце концов, я могу сказать, что Galera работает сейчас довольно хорошо. Это особенно хорошо, если вам нужно обновить сервер БД или выполнить какое-либо другое обслуживание, поскольку это не составляет большой проблемы, если вы отключаете один узел для выполнения какого-либо обслуживания.
Я знаю, что уже поздно, но я оставлю немного своего опыта в кластере Galera здесь. Наше приложение выполняет около 160-200 вставок в секунду, и мы делаем столько же операций чтения. Ночью это намного меньше, но в течение дня это наше среднее значение, и оно может достигать максимальной ставки аренды. Вероятно, мы не находимся в том же контексте вашего приложения, но что помогло нам в то время, когда мы осуществили переход от стандартного MySQL к Galera, было настроить наше приложение на автоматическую фиксацию каждой транзакции, и это немедленно убрало поведение, которое вы описываете в этом вопросе.
В python, использующем библиотеку PySQLPool, мы должны были добавить такую строку в нашу оболочку запроса:
PySQLPool.getNewQuery(self.connection, commitOnEnd=True)
Тогда еще одна проблема, с которой мы столкнулись, заключалась в том, что она недостаточно быстро записывала данные в таблицы. Один из способов сделать это достаточно быстрым - использовать опцию innodb_flush_log_at_trx_commit. Поскольку мы можем позволить себе потерять транзакцию за 1 секунду, мы установили настройку в нашем my.cnf следующим образом:
innodb_flush_log_at_trx_commit = 0
С этими двумя простыми настройками мы работаем уже более года, используя Galera, и 3 сервера работают хорошо с нашим приложением.
Лучший.