Тяжелая запись в кластер 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 сервера работают хорошо с нашим приложением.

Лучший.

Другие вопросы по тегам