SELECT ... FOR SHARE/UPDATE и проверке внешних ключей. Когда одну строку блокируют несколько транзакций, PostgreSQL не может сохранить их прямо в
t_xmax: это поле в заголовке записи вмещает только одно значение. Поэтому в строке хранится идентификатор мультитранзакции, а ее состав PostgreSQL берет из pg_multixact: offsets указывает смещение, members хранит список участников.Проблема была в том, что
offsets оставался 32-битным. При этом мультитранзакции неизменяемы: если к блокировке добавляется еще одна транзакция, создается новая структура. Из-за этого при повторных блокировках одной и той же строки офсеты могут расти квадратично — 1, 3, 6, 10. На нагруженных системах это создавало реальный риск переполнения, а заметить его заранее было непросто.Теперь PostgreSQL использует 8-байтные
offsets, и риск такого переполнения минимален. Компромисс тоже есть: сегменты offsets выросли вдвое, а при обновлении нужна дополнительная конвертация через pg_upgrade. Но взамен PostgreSQL получает больше запаса до жестких лимитов и более предсказуемое администрирование.Подробно о том, как устроены мультитранзакции, почему именно
offsets были узким местом и что меняет этот патч, рассказали на Хабре.Читайте нас в MAX 🤩
