Полагаю, значительная часть ваших проблем со зрением в том, что сайты такие чёрные. А вот когда Хабр и Пикабу белые, то даже на 15" ноутбуке они превосходно читаются. Специально замерил рулеткой расстояние до глаз — те же 50 см...
Это всё прекрасно, но. Как-то мне захотелось винтажный ноутбук. Я его купил, отмыл, собрал, докупил на Али недостающие запчасти... И в конце концов оказалось, что не работает браузер. Ему тупо не хватает процессорной мощности. То, что задумывалось как «тонкий клиент», разрослось до такой толщины, что пожрало всё. И ведь дело не в самом браузере, а в сайтах, когда простая страничка с постом и десятком каментов «весит» несколько мегабайт, а уж внутри у неё такое, что - - -
Как-то мне довелось писать код, который должен был компилироваться и работать под Windows и PalmOS. Там ко всем прелестям, перечисленным в статье (порядок бит, поведение при нарушении выравнивания) добавлялась ещё многозадачность: в WIndows — полноценная вытесняющая, встроенная в операционную систему, а в PalmOS приложению даётся один поток, и внутри этого потока надо самостоятельно реализовать кооперативную многозадачность...
Ну согласование земли — вечный вопрос. Вы же знаете, почему в США ЦОДы всех крупных компаний кучкуются вокруг 40 параллели? Именно потому, что вдоль неё идёт железная дорога, принадлежащая одному собственнику.
Если первая строка во второй транзакции не меняется, то нарушений нет, и транзакции сериализуются в порядке 2-1. А вот если меняется, то возникает аномалия. Какая именно аномалия - зависит от того, какую строку прочитает первая транзакция. Если повтроно первую, то будет unrepeatable read, а если вторую - то read skew. А если перечитает и первую, и вторую, то опять транзакции сериализуются как 2-1.
Беда в том, что мы с вами вот так рассуждаем, а в реальных системах нет таких сторонних наблюдателей, которые могли бы подсказать приложению, что надо перечитать. Поэтому базы данных с переменным успехом изобретают всякие механизмы изоляции :-)
Ну если читатель не верит мне, то может и погуглить. Это ж вы писали, что «автор не понимает, о чём пишет», а не абстрактный «читатель».
На первом шаге я не читал «список строк», я читал единственную строку. Когда я выбираю одну строку из базы, я вовсе не имею в виду «догадайся, что я буду читать, составь список и дай мне первую строку». Я имею в виду именно «дай мне одну строку». А уж как СУБД это реализует — совсем другой вопрос. Ещё раз повторю: физические механизмы для избавления от non-repeatable read и read skew — одни и те же, но аномалии — разные. Это вы почему-то привязались к одной физической модели данных и считаете, что по-другому не бывает. А оно бывает, ещё как.
Аргумент к массовости - это вообще какой-то детский сад. Тем более, что сейчас в моде мультимодальные СУБД
Я понимаю, что чукча не читатель, а писатель, но всё же прежде, чем писать свои статьи, ознакомьтесь хотя бы с классикой. В частности, со статьёй Майкла Стоунбрейкера 1990 года «Манифест СУБД 3 поколения». Принцип 1 — как раз про «разнообразные структуры данных», то, что позже назвали «мультимодальными СУБД». А вот принцип 2 — про то, что не надо ломать старое. То есть если что-то массово используется, это не оттого, что все дураки, а автор той статьи, на которую Стоунбрейкер отвечал, единственный д’Артаньян. А оттого, что это удобно.
Ну то есть вы даже не просмотрели оглавление, а уже переживаете за читателей. Сами-то понимаете, как это выглядит?
Первая транзакция видит ровно то же самое состояние
Ну конечно же нет. Если погуглить «read skew example», то можно найти примеры.
Допустим, есть три строки, в которых обозначены дежурные врачи, и в первую смену дежурит врач Х: [ 1:X, 2:Y, 3:Z ]. Теперь врач X читает первую строку. В это время врач Y переносит своё дежурство на первую смену, меняя местами себя и X и подтверждает транзакцию. Теперь таблица выглядит так: [ 1:Y, 2:X, 3:Z ]. Врач X хочет перенести своё дежурство с утра и читает оставшиеся строки: [ 2:X, 3:Z ]. И теперь он видит, что у него два дежурства — утром и днём!!!
Если бы он перечитал строку 1, то увидел бы, что там теперь Y, и это была бы аномалия non-repeatable read. Но он её не читает, и натыкается на другую аномалию, read skew. Если вы внимательно посмотрите на диаграмму уровней изоляции, то увидите, что эти аномалии исчезают одновременно, и технические методы для борьбы с ними одинаковые. Но, тем не менее, это разные аномалии.
в виде смещения в файле, где все записи хранятся упорядоченно по этому ключу
Эхм... Я вам не случайно написал про PostgreSQL: там смещение может меняться обычной операцией UPDATE. Так что в качестве первичного ключа — так себе атрибут. В Oracle и MS SQL — не может. Ну а если мы возьмём всякие нетрадиционные СУБД на LSM-деревьях (Cassandra, Cockroach... тысячи их, в общем), то там и смещение, и сам файл меняются несколько раз, причём абсолютно независимо от воли администратора.
Есть, конечно, вариант, когда записи хранятся упорядоченно по ключу — в Db2, например. Вы книжку-то почитайте. Автор, может, и не понимает, о чём пишет, но рецензировали её неглупые люди :)
В нормальных СУБД
Только вот почему-то сообщество примерно полвека как «нормальными» считает именно реляционные, а всякие СУБД типа «ключ—значение» постепенно обзаводятся SQL-движками. Не знаете, почему такое происходит?
Второй шаг не «либо», а ломает согласованность. И первая транзакция видит состояние базы, которого при сериализации не было бы.
всё хранится упорядоченно
Вас обманули. Попробуйте в PostgreSQL залить в таблицу какое-то количество строк, сделать SELECT без ORDER BY и запомнить порядок строк. Потом обновите несколько строк командой UPDATE и снова сделайте SELECT. Порядок изменится. А вот в Oracle — не изменится, но это именно что особенности физической реализации.
имеет как минимум первичный индекс
И снова вас обманули. Oracle, PostgreSQL, DB2 и Microsoft SQL Server позволяют создать таблицу без первичного ключа. В MySQL и SQLite опять же в силу особенностей так нельзя, да и в распределённых системах первичный ключ становится обязательным, но вообще реляционная таблица не обязана его иметь.
пачку вторичных
Индекс — вспомогательная структура, нужная именно что «для ускорения работы». Если вы убьёте индекс или построите новый, то все запросы, которые были корректны, так и останутся корректными, а некорректные не станут верными. СУБД исключительно сама решает, когда ей пользоваться индексами.
Автор там очень хорошо понимал, о чём пишет (на всякий случай автор — это я :))
Если вы рассматриваете транзакцию только как совокупность изменений, то перестановка первого и второго шага действительно ни на что не влияет. Но транзакция — это ещё и чтения. Если первый и второй шаг поменять местами, то транзакции действительно сериализуются, а если нет — то нет.
Если будете думать над примерами, то помните, что в базе могут быть инварианты, которые не описываются ограничениями целостности, а базируются только на логике приложения. Классический пример — дежурство врачей: надо, чтобы в каждую смену был дежурный врач.
А вот вы как раз пишете очень странные вещи. В реляционной теории нет понятия «индекса» и, соответственно, не может быть такой аномалии как «невоспроизводимое чтение индекса». Индекс — это всего лишь вспомогательная структура данных, абсолютно прозрачная для клиента. Клиент не может «прочитать индекс».
Аномалии описываются наблюдаемым эффектом, а уже дальше производители придумывают всякие хитрые механизмы, чтобы избавиться от этих эффектов. В частности, для избавления от фантомов делают диапазонные блокировки.
Стэнфорд — огромный университет с замечательной историей, куда стремятся лучшие абитуриенты со всего мира... а отношение к выпускникам — вот такое. Причём не исключено, что отношение заслуженное :)
Уверены ли вы, что к выпускникам вашего кластера не будут относиться так же? (так-то это неуклюжая подколка, но мало ли...)
Вы правы, это разные проблемы, и первая с алгоритмом формирования первичного ключа никак не связана. «Ерунда» — объединять две проблемы в одну.
Если бизнес-логика не требует поиска по дате, то второй индекс, конечно, не нужен. А вот если требует, то надо создать второй индекс, а не запихивать неявно дату в ключ. Ну элементарная же гигиена.
Ну там же комментатор пишет «впихнуть в ключ номер шарда». Так-то да, обычно шардирование двухуровневое: хеш-сумма — номер фрагмента, а потом консистентным хешированием или рандеву — номер шарда. Но иногда встречается и вот такое :))
Полагаю, значительная часть ваших проблем со зрением в том, что сайты такие чёрные. А вот когда Хабр и Пикабу белые, то даже на 15" ноутбуке они превосходно читаются. Специально замерил рулеткой расстояние до глаз — те же 50 см...
Это всё прекрасно, но. Как-то мне захотелось винтажный ноутбук. Я его купил, отмыл, собрал, докупил на Али недостающие запчасти... И в конце концов оказалось, что не работает браузер. Ему тупо не хватает процессорной мощности. То, что задумывалось как «тонкий клиент», разрослось до такой толщины, что пожрало всё. И ведь дело не в самом браузере, а в сайтах, когда простая страничка с постом и десятком каментов «весит» несколько мегабайт, а уж внутри у неё такое, что - - -
У меня на корпоративном компе заблокированы usb и все облачные диски. Но вот scp не заблокирован :-)
Как-то мне довелось писать код, который должен был компилироваться и работать под Windows и PalmOS. Там ко всем прелестям, перечисленным в статье (порядок бит, поведение при нарушении выравнивания) добавлялась ещё многозадачность: в WIndows — полноценная вытесняющая, встроенная в операционную систему, а в PalmOS приложению даётся один поток, и внутри этого потока надо самостоятельно реализовать кооперативную многозадачность...
Ну согласование земли — вечный вопрос. Вы же знаете, почему в США ЦОДы всех крупных компаний кучкуются вокруг 40 параллели? Именно потому, что вдоль неё идёт железная дорога, принадлежащая одному собственнику.
P. S. А статья замечательная.
Ну формально вы правы, надо будет во втором издании этот момент чуть подробнее разобрать.
Увы, не значит.
Если первая строка во второй транзакции не меняется, то нарушений нет, и транзакции сериализуются в порядке 2-1. А вот если меняется, то возникает аномалия. Какая именно аномалия - зависит от того, какую строку прочитает первая транзакция. Если повтроно первую, то будет unrepeatable read, а если вторую - то read skew. А если перечитает и первую, и вторую, то опять транзакции сериализуются как 2-1.
Беда в том, что мы с вами вот так рассуждаем, а в реальных системах нет таких сторонних наблюдателей, которые могли бы подсказать приложению, что надо перечитать. Поэтому базы данных с переменным успехом изобретают всякие механизмы изоляции :-)
Ну если читатель не верит мне, то может и погуглить. Это ж вы писали, что «автор не понимает, о чём пишет», а не абстрактный «читатель».
На первом шаге я не читал «список строк», я читал единственную строку. Когда я выбираю одну строку из базы, я вовсе не имею в виду «догадайся, что я буду читать, составь список и дай мне первую строку». Я имею в виду именно «дай мне одну строку». А уж как СУБД это реализует — совсем другой вопрос. Ещё раз повторю: физические механизмы для избавления от non-repeatable read и read skew — одни и те же, но аномалии — разные. Это вы почему-то привязались к одной физической модели данных и считаете, что по-другому не бывает. А оно бывает, ещё как.
Я понимаю, что чукча не читатель, а писатель, но всё же прежде, чем писать свои статьи, ознакомьтесь хотя бы с классикой. В частности, со статьёй Майкла Стоунбрейкера 1990 года «Манифест СУБД 3 поколения». Принцип 1 — как раз про «разнообразные структуры данных», то, что позже назвали «мультимодальными СУБД». А вот принцип 2 — про то, что не надо ломать старое. То есть если что-то массово используется, это не оттого, что все дураки, а автор той статьи, на которую Стоунбрейкер отвечал, единственный д’Артаньян. А оттого, что это удобно.
Ну то есть вы даже не просмотрели оглавление, а уже переживаете за читателей. Сами-то понимаете, как это выглядит?
Ну конечно же нет. Если погуглить «read skew example», то можно найти примеры.
Допустим, есть три строки, в которых обозначены дежурные врачи, и в первую смену дежурит врач Х: [ 1:X, 2:Y, 3:Z ]. Теперь врач X читает первую строку. В это время врач Y переносит своё дежурство на первую смену, меняя местами себя и X и подтверждает транзакцию. Теперь таблица выглядит так: [ 1:Y, 2:X, 3:Z ]. Врач X хочет перенести своё дежурство с утра и читает оставшиеся строки: [ 2:X, 3:Z ]. И теперь он видит, что у него два дежурства — утром и днём!!!
Если бы он перечитал строку 1, то увидел бы, что там теперь Y, и это была бы аномалия non-repeatable read. Но он её не читает, и натыкается на другую аномалию, read skew. Если вы внимательно посмотрите на диаграмму уровней изоляции, то увидите, что эти аномалии исчезают одновременно, и технические методы для борьбы с ними одинаковые. Но, тем не менее, это разные аномалии.
Эхм... Я вам не случайно написал про PostgreSQL: там смещение может меняться обычной операцией UPDATE. Так что в качестве первичного ключа — так себе атрибут. В Oracle и MS SQL — не может. Ну а если мы возьмём всякие нетрадиционные СУБД на LSM-деревьях (Cassandra, Cockroach... тысячи их, в общем), то там и смещение, и сам файл меняются несколько раз, причём абсолютно независимо от воли администратора.
Есть, конечно, вариант, когда записи хранятся упорядоченно по ключу — в Db2, например. Вы книжку-то почитайте. Автор, может, и не понимает, о чём пишет, но рецензировали её неглупые люди :)
Только вот почему-то сообщество примерно полвека как «нормальными» считает именно реляционные, а всякие СУБД типа «ключ—значение» постепенно обзаводятся SQL-движками. Не знаете, почему такое происходит?
rm -rf *
Второй шаг не «либо», а ломает согласованность. И первая транзакция видит состояние базы, которого при сериализации не было бы.
Вас обманули. Попробуйте в PostgreSQL залить в таблицу какое-то количество строк, сделать
SELECT
безORDER BY
и запомнить порядок строк. Потом обновите несколько строк командойUPDATE
и снова сделайтеSELECT
. Порядок изменится. А вот в Oracle — не изменится, но это именно что особенности физической реализации.И снова вас обманули. Oracle, PostgreSQL, DB2 и Microsoft SQL Server позволяют создать таблицу без первичного ключа. В MySQL и SQLite опять же в силу особенностей так нельзя, да и в распределённых системах первичный ключ становится обязательным, но вообще реляционная таблица не обязана его иметь.
Индекс — вспомогательная структура, нужная именно что «для ускорения работы». Если вы убьёте индекс или построите новый, то все запросы, которые были корректны, так и останутся корректными, а некорректные не станут верными. СУБД исключительно сама решает, когда ей пользоваться индексами.
Не пишите такого больше никогда.
Автор там очень хорошо понимал, о чём пишет (на всякий случай автор — это я :))
Если вы рассматриваете транзакцию только как совокупность изменений, то перестановка первого и второго шага действительно ни на что не влияет. Но транзакция — это ещё и чтения. Если первый и второй шаг поменять местами, то транзакции действительно сериализуются, а если нет — то нет.
Если будете думать над примерами, то помните, что в базе могут быть инварианты, которые не описываются ограничениями целостности, а базируются только на логике приложения. Классический пример — дежурство врачей: надо, чтобы в каждую смену был дежурный врач.
А вот вы как раз пишете очень странные вещи. В реляционной теории нет понятия «индекса» и, соответственно, не может быть такой аномалии как «невоспроизводимое чтение индекса». Индекс — это всего лишь вспомогательная структура данных, абсолютно прозрачная для клиента. Клиент не может «прочитать индекс».
Аномалии описываются наблюдаемым эффектом, а уже дальше производители придумывают всякие хитрые механизмы, чтобы избавиться от этих эффектов. В частности, для избавления от фантомов делают диапазонные блокировки.
С уровнями изоляции у вас сильно упрощённая картинка, реальная намного сложнее. Например, в книге на странице 218.
А вот применить такой же подход к уровням согласованности в распределённых системах — отличная идея. С вашего позволения возьму на вооружение.
Стэнфорд — огромный университет с замечательной историей, куда стремятся лучшие абитуриенты со всего мира... а отношение к выпускникам — вот такое. Причём не исключено, что отношение заслуженное :)
Уверены ли вы, что к выпускникам вашего кластера не будут относиться так же? (так-то это неуклюжая подколка, но мало ли...)
Воистину Perl-программу можно написать на любом языке!
Посмотрите первые кадры фильма «Офисное пространство» («Office Space»)
И от размера штанов
Вы правы, это разные проблемы, и первая с алгоритмом формирования первичного ключа никак не связана. «Ерунда» — объединять две проблемы в одну.
Если бизнес-логика не требует поиска по дате, то второй индекс, конечно, не нужен. А вот если требует, то надо создать второй индекс, а не запихивать неявно дату в ключ. Ну элементарная же гигиена.
Ну там же комментатор пишет «впихнуть в ключ номер шарда». Так-то да, обычно шардирование двухуровневое: хеш-сумма — номер фрагмента, а потом консистентным хешированием или рандеву — номер шарда. Но иногда встречается и вот такое :))