Зміст дописунатисність на посилання, щоб перейти до потрібного місця
Перевіряєте останній ID в базі, а він неочікувано більший ніж реальна кількість записів. Чому таке стається?
У Heroku (та загалом у PostgreSQL) значення ID можуть бути непослідовними через кілька причин:
Автоінкрементне поле (serial / bigserial) та транзакції
- У Rails ID зазвичай є serial або bigserial, що використовує SEQUENCE для генерації унікальних значень.
- Якщо транзакція, в якій було виділено ID, скасовується (ROLLBACK), це значення вже не використовується, але SEQUENCE інкрементується далі. Наприклад, якщо створили об'єкт з id = 4, а потім скасували транзакцію, наступний запис отримає id = 5, а 4 залишиться пропущеним.
Паралельні запити
- У хмарних середовищах, таких як Heroku, може бути багато конкурентних процесів, які записують у базу одночасно.
- Якщо два запити одночасно створюють нові записи, вони можуть отримати ID у різних порядках.
Перезапуск Dyno (Heroku) та кешування SEQUENCE
- PostgreSQL кешує значення SEQUENCE, що допомагає підвищити продуктивність.
- Якщо Dyno (сервер Heroku) перезапуститься, кешовані значення можуть бути втрачені, і PostgreSQL перескочить кілька ID.
Видалені записи
- Якщо ви видаляєте записи з таблиці (DELETE), їхні ID не перевикористовуються.
- Наприклад, якщо були записи ID = 1, 2, 3, потім ви видалили 2, наступний ID все одно буде 4.
Як перевірити SEQUENCE?
Виконайте в консолі PostgreSQL:
SELECT last_value, is_called FROM your_table_id_seq;
Або вручну скиньте значення:
SELECT setval('your_table_id_seq', (SELECT MAX(id) FROM your_table));
Це вирівняє SEQUENCE, але не заповнить прогалини у вже створених ID. Це нормальна поведінка PostgreSQL. Якщо вам критично потрібні послідовні ID, можна використовувати ROW_NUMBER(), але для основного ID це не рекомендується.