The post has been translated automatically. Original language: Russian
Topic
To change the database schema on an empty project is one line. Changing it on a running service with live users is a separate task, where an error costs several minutes of unavailability or lost data.
What is dangerous on large tables
Adding a column with a default value. In older versions of the DBMS, this is a rewrite of the entire table under lock. New ones are often safe, but you need to check your version.
Creating an index in the usual way. The table is locked for writing until the end of the operation. Almost everywhere there is an option with parallel construction, and it is needed.
Changing the column type. As a rule, it means a complete rewrite of the data.
Deleting or renaming a column at the same time as the code is being deployed. At the time of the rollout, some instances are running on the old version and accessing what is no longer there.
The fourth point is the most underestimated. The problem is not the migration itself, but the fact that the code and schema are not changing at the same time.
A multi-step deployment scheme
To rename a column, the sequence looks like this.
Add a new column without deleting anything.
Embed code that writes to both places and reads from the old one.
Fill in a new column for existing rows in batches rather than a single query.
Switch the reading to a new column and make sure everything is working.
Stop writing to the old one and only then delete it, in a separate release.
Five steps instead of one, but at each stage you can roll back and at no point is there an incompatibility between the code and the schema.
Rules that save nerves
Fill in data with batch files with pauses. One UPDATE of ten million rows creates a long transaction, bloats the log and interferes with the rest of the requests.
Set the timeout to lock. Migrations that couldn't take the lock quickly should drop instead of queuing up and stopping all traffic.
Check migration against copies of real data. On a test database of thousands of lines, everything is always fast.
Keep migrations reversible where possible, and know the rollback plan in advance if not.
Do not combine schema changes and logic changes in one release. If there is a problem, it will be unclear what to roll back.
The main thing
Secure migration is not about tricky SQL, but about the fact that the schema and code are always compatible in both directions. Once this condition is met, the deployment ceases to be an event that the team prepares for in the evening after the traffic.
Do you do migrations during business hours or still at night?
После серьёзного сбоя команда обычно проходит один и тот же путь: чинят, выдыхают, коротко обсуждают и возвращаются к задачам. Через несколько месяцев похожий сбой повторяется. Причина не в памяти команды, а в том, что разбор либо не проводился, либо превратился в выяснение, кто нажал не туда.
Почему поиск виноватого не работает
Ошибку почти всегда совершает человек, у которого была возможность её совершить. Если один неверный флаг в команде разворачивает сломанную версию на весь трафик, проблема не в человеке, а в отсутствии защиты. Наказание никак не мешает следующему человеку сделать то же самое, зато надёжно учит команду не рассказывать о сбоях, пока их можно скрыть. И тогда вы теряете самое ценное: раннюю информацию.
Что должно быть в разборе
Хронология в фактах и с временными метками. Когда началось, когда заметили, когда поняли причину, когда починили. Без оценок и объяснений на этом этапе.
Влияние в измеримом виде. Сколько пользователей затронуто, сколько времени, какие операции не выполнились. «Было плохо» это не описание влияния.
Как узнали о проблеме. Если от пользователей, а не от мониторинга, это отдельная находка, часто более важная, чем сама причина.
Что помогло и что помешало при устранении. Отсутствие доступа, устаревшая инструкция, невозможность быстро откатиться.
Действия с ответственным и сроком. Пункт без имени и даты это не действие, а пожелание.
Разница между причиной и триггером
Триггер это то, что запустило сбой: конкретный деплой, конкретный запрос, конкретная нагрузка. Причина это то, что позволило триггеру привести к сбою. Разбор, который останавливается на триггере, заканчивается выводом «будем внимательнее». Разбор, который идёт дальше, обычно приходит к отсутствию проверки, отсутствию ограничения или отсутствию алерта, и это уже можно исправить.
Два числа, которые стоит считать
Время до обнаружения и время до восстановления. Полностью избежать сбоев невозможно, а вот сократить эти два интервала вполне реально, и именно они определяют, заметят ли пользователи проблему вообще. Если время до обнаружения стабильно больше времени до починки, вкладываться нужно в мониторинг, а не в код.
Про формат
Разбор не обязан быть документом на десять страниц. Половина страницы, написанная в течение двух дней и доступная всей команде, полезнее идеального отчёта через месяц. Главное, чтобы он был письменным и находимым: разговор на созвоне через полгода не найдёт никто.
А у вас постмортемы пишутся всегда или только после крупных инцидентов?