Большие апдейты

August 23, 2016

Один долгий руби процесс у нас пишет логи своего выполнения в базу.

Сделано было просто и прямолинейно, создали колонку log:text в таблице скажем jobs и вот такой метод логирования:

class Job
  def log(msg)
    self.log += msg + "\n"
    safe!
  end
end

Конструкция исправно работала пару лет и вдруг закончилось дисковое пространство на боксе с базой. Добавили. Через некоторое время снова закончилось. Начали разбираться.

Оказалось, что кто-то добавил отладочной информации и количество записей в лог резко выросло. Поле log стало занимать 2-3 мегабайта, новые строки добавляются примерно раз в секунду, а Postgres устроен так, что UPDATE = INSERT + DELETE, DELETE же не сразу же освобождает место. То есть мы стали со скоростью несколько мегабайт в секунду забивать диск, автовакуум не успевал чистить.

Починили легко. Вынесли лог в отдельную модель и вместо обновления теперь создаем новую строку в таблице. Добавили пару индексов для скорости доступа и все стало хорошо - место на диске заканчиваться перестало. Это решение успешно работает до сих пор.

comments powered by Disqus