Назад | Перейти на главную страницу

Тяжелая запись в кластер 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 настолько ненадежен, когда вы делаете массовые параллельные записи / обновления? Сложно поверить.

У нас была почти такая же проблема - когда мы обновляли его, не удалось с тайм-аутом блокировки. Наша текущая стратегия состоит в том, чтобы использовать 1 сервер для фоновых процессов и массовых операций записи, а другие 2 сервера использовать для живых веб-серверов.

Это довольно просто, если вы используете HAProxy, но нам также пришлось внести некоторые изменения в наш код.

Пока кажется, что он работает намного лучше, но мы обязательно посмотрим, будет ли он работать нормально через несколько недель (когда мы не столкнемся с теми же проблемами, что и были).

Некоторые заметки из нашего опыта:

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

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

Третий шаг, который мы сделали, - это улучшение фоновых процессов. Во время одной транзакции программист уронил таблицу и перестроил ее с нуля. Мы изменили это, чтобы сначала проверить, необходимо ли изменение, а затем обновить строку. Это значительно улучшило производительность этого процесса.

Наш опыт показывает, что чтение в кластере Galera происходит очень быстро, но запись может быть довольно медленной, особенно если вы выполняете множество операций записи. Вначале у нас были проблемы, и нам пришлось повторно импортировать всю таблицу - это было большим убийством для базы данных. Еще одна вещь, которая дважды приводила к сбою нашего сервера, заключалась в том, что binlog заполнил диски сервера, что привело к сбою сервера. Также не забудьте изменить все базы данных на таблицы 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 сервера хорошо работают с нашим приложением.

Лучший.