Ошибка про spinlock, а виновата хеш-таблица

Во время испытаний перед релизом я обнаружил в логах сообщение stuck spinlock detected. Если вы сталкивались с отладкой конкурентного кода, вы знаете, что это неприятная новость. Где-то в недрах базы данных сломалась синхронизация, а сообщение об ошибке почти ничего не говорит о том, где искать причину.

Самое интересное, что ошибка появилась после, казалось бы, безобидного изменения: я увеличил количество партиций хеш-таблицы с 32 до 64. До этого мой код долгое время прекрасно работал. А теперь всё развалилось.

Расследование вышло долгим и тернистым, поэтому я записал видео, где разбираю баг по шагам. Сегодня оно вышло: 😉 Смотреть на YouTube

Знать устройство PostgreSQL заранее не нужно: всё, что понадобится для выводов в конце, я объясняю по ходу. Что внутри: — 01:39 — демо: 32 партиции работают, 64 падают — 05:12 — как устроена хеш-таблица HTAB: в памяти процесса, в общей памяти, партицированная — 23:44 — почему freelist'ов ровно 32 и почему снаружи вы об этом не узнаете — 34:58 — 64 партиции: гонка и PANIC — 41:34 — вывод, который напрашивается, и почему он неверный — 47:20 — как похожую проблему решили в C++ — 51:29 — каким должен быть API, чтобы такой баг нельзя было написать

Самое обидное: в исходниках PostgreSQL есть комментарий, который прямо предупреждает об этой ловушке. Функция возвращает указатель и сама просит им не пользоваться. Я этот комментарий не прочитал 🤦🏻‍♂️ Почему комментарий плохо защищает от такой ошибки и что защищает лучше, тоже рассказываю в видео.

😉 Смотреть на YouTube

P.S. Две недели назад в P.S. к посту про Claude я жаловался, что увяз в перфекционизме: две попытки съёмки сорвались, потому что подготовка съедала всё время. Выход оказался простым: записал одним дублем, а лишнее вырезал в монтаже. Обложку, правда, всё-таки сделал. Даже три: YouTube сейчас сам проверяет, какая лучше работает 😁


В этом посте были ссылки, но мы их удалили по правилам Сетки