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

Один долгий руби процесс у нас пишет логи своего выполнения в базу.
Сделано было просто и прямолинейно, создали колонку log:text
в таблице скажем jobs
и вот такой
метод логирования:
class Job
def log(msg)
self.log += msg + "\n"
safe!
end
end
Конструкция исправно работала пару лет и вдруг закончилось дисковое пространство на боксе с базой. Добавили. Через некоторое время снова закончилось. Начали разбираться.
Оказалось, что кто-то добавил отладочной информации и количество записей в лог резко выросло.
Поле log
стало занимать 2-3 мегабайта, новые строки добавляются примерно раз в секунду,
а Postgres устроен так, что UPDATE = INSERT + DELETE, DELETE же не сразу же
освобождает место. То есть мы стали со скоростью несколько мегабайт в секунду забивать диск,
автовакуум не успевал чистить.
Починили легко. Вынесли лог в отдельную модель и вместо обновления теперь создаем новую строку в таблице. Добавили пару индексов для скорости доступа и все стало хорошо - место на диске заканчиваться перестало. Это решение успешно работает до сих пор.
Tweet