Маленькая загадка для любителей PostgreSQL
20 июня 2018
Интересный баг нашел в своем проекте. Загадаю загадку, попробуйте отгадать.
CREATE TABLE cats (
cat_id bigint,
name varchar(128) NOT NULL,
PRIMARY KEY (cat_id)
);
INSERT INTO cats VALUES (1, 'Tihon'), (2, 'Marfa');
SELECT * FROM cats;
cat_id | name
--------+-------
1 | Tihon
2 | Marfa
(2 rows)
-- do some magic
SELECT * FROM cats;
cat_id | name
--------+--------
1 | Tihon
2 | Marfa
1 | Tihon2
(3 rows)
В таблице получилось дублирование cat_id, при том, что это primary key. Как такое возможно?
Ответ: наследование таблиц
-- do some magic
CREATE TABLE cats2 (LIKE cats INCLUDING ALL);
ALTER TABLE cats2 INHERIT cats;
INSERT INTO cats2 VALUES (1, 'Tihon2');
Мы делали шардирование таблицы на основе наследования. Изначально у нас была одна таблица. Потом, в какой-то момент, мы поняли, что там будет слишком много данных, и решили ее шардировать.
При этом в базовой таблице уже накопилось записи. По хорошему, их нужно было сразу мигрировать -- перенести из родительской таблицы в дочерние. Но мы решили отложить это дело на потом, а пока обрабатывать ситуацию на уровне приложения. Ну и плохо обработали :)
Интересно было то, что я потом переключился на другой проект, и напрочь забыл про это шардирование. А потом мне сообщили о странных данных в базе, и я смотрю в консоль, вижу несколько дублирующихся primary key, и ничего не понимаю.
Позвал на помощь Сашу. Мы смотрим вдвоем, задумчиво чешем затылки,
и обмениваемся глубокомысленными репликами:
- А какой у нас уровень изоляции транзакций?
- Нормальный.
Потом Саша вспомнил про шардинг, и все стало ясно.
Переключение между проектами дает такие вот побочные эффекты :)