Комментарии 27
В распределенной базе данных auto-incrementing представляет собой серьезную проблему. Для генерации ID необходима глобальная блокировка.
Легко решается без блокировок если в каждой базе будет использоваться свой пул ID.
Например, если у нас две базы, в одной могут генерироваться четные Id, в другой нечетные.
пул идентификаторов идея очень правильная (и без распределенной базы работает, где нет autoincrement), но интервалы или (в общем случае) стратегии генерации должен выдавать глобальный координатор — редко, но метко. Может, какие-то стратегии общего консенсуса тоже сработают — не уверен, что это будет приемлимо быстро. Может быть ситуация, когда ноды подключаются и отключаются и простые решения с "четным-нечетным" перестают работать.
В DB2 с доисторических времен для генерации ключей рекомендовалось generate_unique() основанное на времени и номера сервера для кластерных конфигураций. При этом метка времени не является бессмысленным суррогатом и может, например, ограничивать выборку как предикат или использоваться для шардирования таблицы.
При проектировании БД нужно придерживаться естественных ключей.
При проектировании БД нужно придерживаться естественных ключей.
Не бывает естественных ключей. Все атрибуты, которые действительно являются ключевыми, это искусственно придуманные идентификаторы, во многих случаях автоинкрементные. Всегда могут существовать 2 объекта с одинаковыми характеристиками, одинаковые в смысле в пределах погрешности измерения.
А как только разработчик использует rowid — он не понимает БД от слова совсем.
Ок, какой первичный ключ вы выберете для учета носков?)
rowid и автоинкремент это не совсем одно и то же. Значения в автоинкременте не повторяются и не переиспользуются.
2. Программисты привыкли к массивам и меткам.
Реализация счетчика для БД, в конкурентной среде, задача нетривиальная. При реализация с полной блокировкой возможен только один поток. Вынужденно каждому соединению сервер выделяет блок значений от сиквенса, в результате счетчик перестает быть счетчиком как таковым. Последовательность получения значений и реальный порядок попадания записей в БД нарушается, образуются дыры. При кластерной конфигурации наступает катастрофа, т.к. мастером по сиквенсу может выступать только один сервер и другие вынуждены обращаться к нему — при операциях даже в 1с сетевые задержки уже существенны. Представьте слегка нагруженную oltp базу с 1000 коннектов и 20 тыс транзакций (не операций) в сек. и хотя бы 0.01% из них вдруг замедлиться на 100 ms.
Все вышеописанное, как и статья, относится к промышленным системам. Хотя проблема может выстрелить и при относительно примитивном сценарии — система А передает события с ID типа счетчик в систему Б, система Б по данному ID обеспечивает идемпотентность, счетчик рестартовали…
При этом никто не будет бить по голове разраба, если он использует сиквенс для справочника в сотню строк, который дополняется раз неделю. Хотя и тут возможны проблемы — когда у вас несколько сред, например, тестирования…
в результате счетчик перестает быть счетчиком как таковым
Так нам не нужен счетчик, нам нужны уникальные ключи объектов.
Последовательность получения значений и реальный порядок попадания записей в БД нарушается, образуются дыры.
У GUID между значениями тоже дыры.
т.к. мастером по сиквенсу может выступать только один сервер
Ну можно сделать чтобы часть битов означала номер сервера, тогда будет несколько сиквенсов.
никакой, как и в жизни
если он использует сиквенс для справочника в сотню строк
Так вы на вопрос-то ответьте. У носков нет естественного первичного ключа, как их различать в таблице носков? "Никакой" это не ответ, в таблице должен быть первичный ключ.
Вы совершенно не понимаете, что такое БД.
Мне правда очень интересно.
Вы совершенно не понимаете, что такое БД.
Ага, вот я и думал, ответите вы на вопрос или прицепитесь к этой формулировке. Для целей учета таблицы без первичных ключей бесполезны. Это можно логи какие-нибудь так писать, и то не факт, что это потом не создаст проблем.
Да, кстати:
никакой, как и в жизни
Так у любых объектов "в жизни" нет уникальных атрибутов. О чем я и говорю.
Если у Вас все носки пронумерованы, тут крыть нечем. Это особый случай — для этого обычно применяются key value db.
Изначальный посыл статьи — боль сопровождения, как последствия неудачного проектирования.
Попытайтесь сначала представить процесс не автоматизированным
Снова, я именно об этом и говорю. В неавтоматизированном процессе для учета одинаковых предметов (столы, стулья, носки) применяются инвентарные номера. Искусственный и инкрементный идентификатор.
любимый всеми STATUS — «and status=0». Это значит, что чистые и грязные носки у вас лежат в одном ящике
Ок. И как же одному конкретному носку поставить статус "Грязный"?
UPDATE table SET status = 1 WHERE status = 0 LIMIT 1? А если статус одновременно вводят 2 разных пользователя? Получили гонку по данным и глобальный лок на всю таблицу чтобы ее избежать.
выбирайте глобально уникальный и естественный первичный ключ (например, имя пользователя)
А потом запретите своим пользователям выходить замуж и менять фамилию. И никогда не принимайте на работу Ивана Говнова, а то вдруг он захочет сменить имя на Евгений.
Очевидно же что в данном случае имеется ввиду логин.
В конторе логин основан на фамилии пользователя, так что после развода многие заказывают сменить и фамилию и логин.
У реальных объектов обычно не существует такого свойства, которое гарантированно никогда бы не менялось, так что первичный ключ должен использоваться только для идентификации "да, это тот же самый объект".
Ужас какой. Хоть бы СУБД указали. Ибо для некоторых СУБД сильно лучше ключ bigint чем varchar и тем более uuid
Поэтому при возможности, пожалуйста, выбирайте глобально уникальный и естественный первичный ключ (например, имя пользователя).
А потом требования меняются и глобально уникальный естественный первичный ключ становится не уникальным.
Что такое «count't»?
Или это такая игра слов
«couldn't» + «count» = count't?
Repeatable reads: незафиксированные записи в текущей транзакции доступны для текущей транзакции, но изменения, сделанные другими транзакциями (например, новые строки), не видны.
Wimbo Заранее прошу прощения если я туплю, в Repeatable reads новые строки из других транзакций будут видны, и по вашей ссылки этоже как раз таки и написано.
newly inserted rows by other transactions will be visible
Больше разработчиков должны знать это о базах данных