Информация об изменениях

Сообщение Re[96]: MS забило на дотнет. Питону - да, сишарпу - нет? от 13.10.2021 10:25

Изменено 13.10.2021 10:45 vdimas

Re[96]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:

V>>Это адекватное решение и именно так СУБД работают.

S>Нет. Во всех СУБД, которые поддерживают row locking, блокировка строки и блокировка страницы делается через разные ресурсы, а не через один семафор.

Своим "нет" ты делаешь вид, будто подтверждаешь тезис из своего предыдущего поста, хотя ты говоришь о другом, т.е. твоё "нет" не относится ни к чему.

Будем разгребать:
Синклер:
— Неадекватное решение — реализация набора видов блокировок в СУБД через самописанный семафор, поддерживающий отрицательные значения счётчиков.

Я:
— твоё утверждение ложно, бо в СУБД широко используют именно самописные семафоры.

Синклер:
— нет, блокировка строки и блокировка страницы делается через разные ресурсы, а не через один семафор.

Я:
— а как соотносятся твои "разный" (в плане экземпляров) и "самописный"?
— и почему "блокировка" делается через "ресурсы"? ))

В общем, просьба не применять пока мест просто термин "блокировка", бо ты используешь его неверно уже десяток постов подряд.

Насчёт "ресурсов" буду считать, что ты оговорился.
Если нет — вот одна из первых ссылок в гугле, просто прочти первый абзац, там сходу понятно, что принято называть "ресурсом" в СМО:
https://cyberleninka.ru/viewer_images/16416395/f/1.png

Теперь возвращаюсь к самым первым рассуждениям, бо ты их лихо пролетел и у тебя не осело аж ничего.
В общем, еще раз чуть медленнее, как для самых маленьких:

Чтобы дойти до операции блокировки строки, ты должен сначала пройти уровень блокировки страницы.
Т.е. не заблокировать страницу, но "отметиться" на каком-нить примитиве сигнализации уровня страницы, и, отметившись удачно, запретить конкурентным задачам блокировать страницу. Т.е., shared-владение ресурсом запрещает блокировку ресурса (т.е. запрещает монопольное овладение ресурсом, а не производит это овладение, как может показаться из твоей ошибочной терминологии), т.е., чтобы заблокировать страницу, небходимо будет дождаться освобождения всех shared-владений.

В пред. абзаце выполняется ровно такой же шаг алгоритма, как в случае RO-RW блокировок.
Хотя ни о каком прикладном отношении RO-RW речь не идёт, речь идёт только о shared, либо монопольном владении, просто при shared-владении безопасны конкурентные чтения, вот и всё кино. Но всё это уже уровень прикладной семантики, т.е. интерпретирования состояний неких переменных, изменяемых атомарно.

В данном случае у некоей простейшей СМО (или простейшей такой подсистемы) есть всего два состояния — shared и exclusive.
Как обыграть эту пару состояний — я рассказал более чем доступно, ИМХО.

Но СМО (или её ячейка-посистема) может иметь более двух состояний.
Семантика состояний кодируется выбранным программистом образом, именно для этого я дал обобщённый код атомарного управления переменной самописного "примитива" синхронизации.
Если состояний будет более одного, их, например, можно будет закодировать в старших битах счётчика, и тогда код условия под if потребует наложения маски битового тела счётчика или еще каких проверок, согласно выбранной семантики закодированного значения.

Не зря я в самом начале предложил абстрагироваться от идентификаторов блокировок, а просто пронумеровать их, связав в иерархию, чтобы не засорять моск ненужной информацией.
Точно так же можно абстрактно пронумеровать состояния СМО и построить граф премещения по состояниям.

Стадия анализа задач, про которую я уже совсем не скромно намекаю который пост подряд, должна дать тебе отображение прикладных требований на выбранную схему СМО, адекватную поставленной задаче, включая графы переходов, если состояний более одного. Далее просто кодируются (нумеруются) уровни иерархий, состояния и дуги-сигналы, и затем накладываются те механизмы реализации схемы, о которых я завёл речь с самого начала.


И да, просьба заканчивать буксовать на "единственном семафоре", бо в подробном описании различных алгоритмов RO-RW блокировки ключевой семафор я называл целевым, но никогда не было речи о том, что один семафор может обслужить разные уровни иерархии, если есть такая потребность в разных уровнях. Один он будет на своём уровне.

К тому же, достаточно того, что упоминался "турникет" — а это семафор со счётчиком 1, где "турникетом" его делает способ оперирования этим семафором. Т.е. уже минимум два семафора. И еще требуется сериализация писателей, если есть желание решить проблему голодания писателей в случае, когда мы не управляем задачами, а пользуем семафоры уровня ОС — уже 3 семафора. И это только для разруливания проблематики совместного или монопольного доступа к одному ресурсу.

А ресурсы у тебя иерархические, как матрёшки, и в точности такая же задача возникает на каждом слое матрёшки — об этом было сказано вообще сразу и шло как контекст.
(при переходе от таблицы к странице, до этого при переходе от базы к таблице, до этого на уровне схемы)

И я уже напоминал, что различные уровни изоляции достигаются не только и не столько за счёт блокировок, а чаще за счёт алгоритмов, растущих из банального COW.
Т.е., на некоторых уровнях изоляции конкурентные чтения и даже транзакционная запись может быть, но совершенно без эксклюзивных блокировок "ресурсов", как тебе такое?

И да, в прошлый раз было лень пошариться по и-нету, вот ответ на твои странные вопросы из разряда "а зачем вы рассматривали семафоры ОС и свои самописные, зачем рассуждали об адекватности?"
Сорри, но подобного рода "вопросы" вызывают у меня культурный шок.



S>>>Неадекватное оно по вашим же словам.

V>>Это ты придумать изволишь.
S>Цитирую:
S>

S>Одно но — на многопроцессорной машине в режиме вытесняющей многозадачности наших "очередей" нет, есть очереди уровня ОС, поэтому возможно голодание писателей, т.к. даже при ограничении доступа к ресурсу счётчиком 1, его могут захватить конкурентные потоки-читатели.


1. Где конкретно здесь про адекватность моего решения?
Это про адекватность дефолтного.
Если ты хотя бы из банального любопытства никогда ранее не интересовался алгоритмом RO-RW блокировки, то мог бы найти и ознакомиться на многих углах в инете.

А недефолтные алгоритмы — сплошное ноу-хау, увы.
И почему так — именно тебе не так давно рассказывал уже.


V>>Было показано:

V>>http://www.rsdn.org/forum/flame.comp/8108567.1
V>>И там же ты оставил мой процитированный псевдокод, который позволяет добавить к семафору произвольную операцию.
S>После добавления к семафору "произвольной операции" придётся ещё допилить код выбора между продолжением и ожиданием.

Пфф, очередной культурный шок.
Коду вообще требуется, чтобы его кто-то писал.

Выглядит как когнитивный диссонанс по причине "само не работает".
Т.е., на уровне мозжечка привык рассуждать в духе "с неба упало и само работает", вот до чего дотнет доводит. ))

Только в твоём случае этот феномен доходит до крайности: "обычные люди это сделать не смогли бы, такие как я или любые мои собеседники в интернете".
Отсюда твоя неприятная нервозность и низкий конструктив.


S>В вашем простом примере acquire() полагается на то, что одиночный release освободит достаточно ресурсов для успешного захвата, поэтому после _sema.acquire() можно просто выйти.


В том моём примере счётчик может быть отрицательным, как ты просил показать.
И это требуется для более простого решения задачи про СМО из двух состояний: совместного или исключительного доступа к ресурсу.

Плюс я приводил пример сигнатуры release семафора в Windows АПИ и дотнетных реализациях — у всех за раз можно "освободить" более единицы, т.е., семафоры не обязательно инкрементируют только на единицу. Через отрицательный счётчик ввел еще возможность декремента на произвольное число для надобности описанного алгоритма.
И вообще дал возможность проводить любые вычисления с счётчиком в атомарной манере.

В общем, странно, что эти простейшие телодвижения вызвали у тебя настолько серьезное заклинивание. ))
Не высыпаешься совсем?


V>>Показано.

S>Где? Никакого кода, кроме простейшего легковесного семафора поверх семафора ОС, не приведено.

Этим я ответил на то, про что ты громче всего кричал на той стадии.
Чтобы перейти к следующему вопросу, надо проехать хотя бы этот.
Потом проблематику RO-RW.
Потом обнаружить, что ключевым является управление дисциплиной захвата ресурса, т.е. наличие более одного состояния простейшей одной ячейки СМО.

А у тебя ресурсы вложены аки матрёшки...
А потом, я надеялся, что в этом месте тебя осенит и ты перестанешь задавать неконструктивные вопросы.

V>>И рассказано, что если управлять задачами самостоятельно, то от семафоров уровня ОС можно будет отказаться, по крайней мере в алгоритмах управления задачами, оставив системные семафоры только на случай, когда рабочим потокам нечего делать, чтобы иметь возможность их пробуждать (это я уже повторяюсь, бо ты невнимателен).

S>Я вполне внимателен, просто вы пишете много банальностей и мало кода.

Для тебя не банальности, раз ты буксуешь, та еще так громко.
Я пока не убедился, что ты понял хотя бы описанный мною алгоритм.
И тем более не убедился, что ты понял, как такие алгоритмы вообще разрабатывают — задачи-то разные бывают.


V>>Как код реализации СУБД? ))

S>Именно.

Но ты же не мог всерьёз просить меня ответить тебе работающими исходниками полноценной СУБД? ))
До такого маразма, я надеялся, не дойдёт, поэтому списал на обычную твою нервозность.
И сейчас списываю.


S>Напомню: мы обсуждаем реализацию гипотетической СУБД, которая должна быть эффективнее существующих.


С херна ли эффективнее существующих?
Кто тебе такое обещал?

Мы обсуждаем как оно устроено и работает.
Обсуждение возникло по причине того, что ты злостно путаешь уровни изоляции и "блокировки".

На первой стадии я вполне внятно продемонстрировал, что будучи организованым только поверх примитивов синхронизации ОС, оно будет неадекватно задаче.
А будучи реализованным через ручное управление заявками, можно подключать наработки из СМО — они туда сам просятся и так, вообще-то, и поступают при разработке подобных систем сложных диспетчеризаций заявок.

Не только СУБД.
Я с IP-телефонией одно время имел, там те же СМО, очень похожие задачи.
Твоё зацикливание на СУБД говорит лишь о том, что ты не понимаешь сам этот класс задач.


Возвращаясь ко встроенным примитивам синхронизации — дело не только в дороговизне вызовов АПИ ОС поверх защищённой памяти, еще я раскрыл проблематику турникета, и, вроде бы, вполне однозначно, понять неверно там просто никак.

Еще тебе говорилось, что вместо "различных видов блокировок" (как ты рассуждал в начале этой беседы), стоит оперировать не их именами собственными, а достаточно рассматривать их нумерованную иерархию, бо на каждом уровне иерархии в плане отношений с низлежащим слоем в СУБД соблюдается строгое подобие от уровня выше.
(не всеми уровнями иерархий доступно одинаково развитое управление извне, но "унутре" отношение сущностей одинаковое).


V>>Ты опять задаёшь вопросы не по существу, в рамках обсуждений форума мы можем рассмотреть лишь отдельные моменты, но ты и их понять и продвинуться на шажок дальше пока не в состоянии.

S>Мы сможем двигаться дальше, если вы будете приводить код, а не абстрактные рассуждения про СМО и симуляцию.

СМО — это не абстрактные рассуждения, а вполне конкретные, и сразу же было сказано почему — так УДОБНЕЙ.
Удобней разрабатыать модель, удобней её реализовывать, и эта реализация более адекватна, чем на доступных изкаробки ОС ср-вах.

Про симуляцию — тем более.
Да, просимулировать происходящее можно и на обычных семафорах, в т.ч. используя код того полусамописного семафора, который я дал, т.к. при симуляции обычно не интересует быстродействие эмулятора, интересует происходящее в количественном выражении, т.е., где, какие, сколько операций, какова вероятность/статистика развития тех или иных сценариев из большого комбинаторного их сочетания и т.д. и т.п.

Модель может быть хоть самой тормознутой, от модели требуется быть удобной для программирования/оперирования/развития-модификации.

В общем, мяч пока на твоей стороне, уже ты должен приводить код, хотя бы чтобы продемонстрировать своё понимание.
Где у тебя возникнут сложности — я помогу, как помог с этим семафором, не переживай. ))


V>>Это ты опять невнимателен.

S>Мне цитату привести?

Да, и еще раз да.
Заодно сам еще раз внимательно перечитаешь.


V>>Ну так и перепроверил бы себя, что именно утверждалось.

V>>А то мне на каждый абзац здесь руку-лицо ставить надо.
S>Ок. Цитируем:
S>

S>В отсутствии конфликтов — одна интерлокед-операция на таблицу для скана таблицы.
S>Считай, бесплатно.


И?
Одна на таблицу.
До этого одна на базу.
До этого одна на схему.
До этого минимум одна на входной механизм самописных очередей задач.
До этого на пул запросов, на ресурсы, требуемые для работы хотя бы парсера и валидации SQL, составления плана запроса согласно текущей схемы базы и т.д. и т.п.

Но в дефолтном алгоритме RO-RW блокировки аж три семафора, три недешёвых вызова АПИ ОС только на реализацию всего двух состояний СМО всего одного уровня из иерархии.
Разве не ого? ))

А если состояний "ячейки" СМО более одного (как ты там упоминал еще виды блокировок) — то и вовсе по-дефолту обычно делают на условной переменной, со всеми её suspicion wake up и чудовищной вероятности столкновения потоков на единственном мьютексе, обслуживающем эту условную переменную.


V>>Чтобы осмысленно возражать, тебе сначала придётся показать, что этот алгоритм не отвечает задаче переключения дисциплины обслуживания ресурса.

V>>И что-то мне подсказывает, что как только ты попытаешься это показать, т.е. включишь моск, многие вопросы отпадут сами собой.
S> Показываю на пальцах: Допустим, у нас уровень параллельности = 8. Разделяемые блокировки на ресурсе реализуются как acquire(1), эксклюзивные — как acquire(8).
S>Блокировки строки — опять же, acquire(1), страницы — acquire(8).

8 будет если на данном уровне иерархии ровно 8 фактических shared-владений.
А если одно?
А если ни одного?
Ты там цикл не видел разве в псевдокоде обновления счётчика?


S>Транзакция A продолжает работу, захватывает shared lock на записи номер 4, 5, 6, 7, 8, 9, 10 при помощи Page(42).acquire(1) — успешно.


Зачем?
Ты ведь уже shared-владешь страницей, т.е. можешь читать данные этой страницы "просто так".
Это тогда надо заходить на страницу под другой дисциплиной блокировки, например, "я могу блокировать с разными дисциплинами произвольные твои строки конкуретно", и тогда страница не пустит shread-RO "клиентов" к себе.

И тогда acquire ты будешь запрашивать у конкретной строки, а не страницы, бо на страницу под нужной тебе прикладной дисциплиной ты уже вошёл.

Или, при реализации COW, если страница захвачена читателями и для тех уровни изоляции позволяют, твоя транзакция может поступить иначе — сделать копию страницы, обновить строки в этой копии, а потом обновит цепочку страниц (про COW тебе тоже говорилось сразу).

А текущая страница для shared RO-заявок переходит в режим фантома и будет жить до тех пор, пока ею shared-владеют, потом тихо умрёт.


S>Хотим захваттить shared lock на запись №11. Упс — кончился уровень параллелизма, встаём в дедлок


Здесь опять путаешь уровни иерархий.
Говорил же тебе — тупо пронумеруй, меньше вероятность ошибиться. ))


S>Нет, так нельзя, надо увеличивать уровень параллелизма до MAXPAGERECORDS.


В системе с хаотическими заявками из хаотичных потоков может и надо, смотря как реализовано.
Но тогда привет турникетам и база быстро встанет колом, при таком-то кол-ве уровней иерархии.


S>В общем, предлагаемый вами механизм заведомо неполон.


В общем, я пока не вижу понимания даже на 10%.
Мне пока кажется, что ты уже понял про "гибкий" семафор, твой тон в этой области снизился, будем считать это за признаки понимания, ОК.

Надеюсь, на следующей итерации у тебя будет получше с пониманием целевого — а зачем вообще требуется нетривиальная возня с режимами СМО.

И важное про уровень параллелизма.
Тут ты еще напутал сами ресурсы.
Про уровни параллелизма когда речь, то ресурсом является вычислительный блок, (процессор, ядро, поток в ядре и т.д., смотря как железка устроена).

Например, транзакция, выполняющая COW, делает обновления многошагово, т.е. через последовательность заявок.
Первая заявка иницировала транзакцию, произвела первое чтение.
Если были конкуретные чтения или даже чтения-записи, то в рамках транзакции могут создаваться копии данных, как упомянул выше. Одна операция чтения — один уровень параллелизма (допустим для простоты). В системах с отказами и последействиями, например, нужной страницы нет в памяти, — будет отказ и новая постановка в очередь с новым состоянием заявки (см эту категоризацию СМО, сама эта категоризация даёт много подсказок).

Т.е., диспетчер одного "физического" потока может рассматривать в т.ч. "параллельную" очередь заявок, беря на исполнение те, к которым к требуемым ресурсам есть доступ (список ожидаемых ресурсов, в свою очередь, может представлять из себя круговую очередь).

Освободили "ресурс", т.е. процессор-ядро-поток, исполняем следующую заявку. Вполне может быть, что следующей будет заявка из той же самой транзакции, она ведь при инициализации могла накидать сразу пачку заявок, т.е. вероятность последовательного расположения заявок от одной транзакции будет высокой.


S>Его можно допилить до требуемого уровня функциональности, но, повторюсь уже в третий раз, вы получите ровно те же блокировки, которые мы наблюдаем в промышленных СУБД.


Не, мистер Блейн, с "промышленными" СУБД я не спорил, я тебе их объясняю, бо ты путал блокировки и уровни изоляции.
Я отделяю для тебя мух от котлет.

В общем, тебе придётся найти подтверждение этой (уже не первой) инсинуации или прилюдно извиниться.


S>И их виды, и их иерархию. И код исполнения запроса будет точно таким же, как у всех — внутрь цикла сканирования мы будем вставлять вызовы _lockManager.AcquireSharedLock(_rowID).

S>Если вы попробуете на коленке набросать код этого метода, то поймёте, о чём я говорю.

Ага, т.е. я прав — ты теперь пытаешься замылить саму суть обсуждения, как обычно ища виноватых в своем непонимании на стороне. ))

Рановато, мистер Блейн, фокус не удался.
"На коленке" я жду от тебя куда как более примитивную часть этого кода — простое управление shared-exclusive доступом ко всего одному ресурсу, т.е. очень простой СМО из двух состояний.

И жду понимание того, как с помощью аналогичных механизмов, раскиданных по разным уровням иерархий, реализовать комбинаторику возникающих сценариев при организации различных уровней изоляции.

И тогда ты будешь готов согласиться с самыми первыми моими заявлениями, насчёт простой нумерации уровней иерархий.
Пока что ты от этого слишком далек.


V>>Заведомый ACID можно обеспечить исключительно и только одним глобальным мьютексом, через сериализацию доступа.

S>Ну конечно же нет.

Ну конечно же да.
Потому что в какой-нить транзакции я могу по некоему условию менять даже схему таблиц, т.е. заранее неизвестно.
И тогда ACID на всех уровнях, кроме сериализованного не будет соблюдаться от момента начала такого участка транзакции, т.е. базе придётся войти в сериализованный режим.

А всего-то самый верхний уровень иерархии, никаких тебе эзотерических рассуждений с придыханиями.


S>Почитайте любой учебник по СУБД.


Опять мимо, тут нужен учебник не для пользователя СУБД, а для разработчика СУБД (угу, не разработчика прикладной базы данных, а самой СУБД).
СМО — неотъемлимая часть такого учебника.


S>Вас не настораживает, что блокировочники на уровне изоляции serializable не делают один глобальный мьютекс на базу?


Это смотря что транзакция делает, т.е. на каком уровне иерархии работает.
Exclusive lock на уровне конкретной таблицы — это та самая сериализация доступа к этой таблице.


S>Глобальная блокировка является достаточным, но вовсе не необходимым условием для serializability.


Опять та же ошибка — зависит от уровня иерархии оперируемой сущности.
Еще раз — пронумеруй, будешь меньше путаться.


V>>Требуется, наоборот, обеспечить уровни изоляции худшие, чем сериализованный, с целью увеличения уровня конкурентности системы.

S> Для начала разберитесь с serializable.

Не прокатило.
На данной стадии ты можешь или тихо слиться, или взять себя в руки, наконец, и разобраться с предметной областью.
Она не слишком сложная, в сети мильон конспектов лекций.

СУБД тут ни разу не уникальны, т.е. до смешного — сама попытка отослать к учебнику по некоей СУБД демонстрирует не просто непонимание предметной области, а отсутствие простой "записи" в эрудиции о наличии самой предметной области.


V>>Это если ты верно используешь термин "блокировка" в IT, где этот термин подразумевает исключительное владение ресурсом.

S>В СУБД блокировки бывают не только исключительными. Блокировка означает некоторую степень владения ресурсом.

В английском различают термины lock и block, в русском языке возникает путаница.
Поэтому, стоит использовать или английскую терминологию, или длинную русскую, навроде "блокировка для совместного доступа по чтению".

В русскоязычном IT "просто блокировка" означает blocking lock на английском.


S>Далее, вам нужно повторно изучить раздел "изоляция транзакций" в более-менее любом учебнике, и разобраться, почему "допущения, ухудшающие ACID", не обязательно приводят ни к несогласованности, ни к отказам/конфликтам.


"Не обязательно" не канает.
Речь же о статистике-вероятности.

На пальцах — ты можешь забыть защитить изменяемую из разных потоков переменную мьютексом, но это не обязательно приведёт к конфликтам-несогласнованности.
Как карты лягут.

Простой пример:
вот у тебя запрос с агрегацией только по чтению.

Какие могут быть уровни изоляции:
— никакой, т.е. код исполнения запроса читает и те данные, что уже есть и те, что были изменены; есть вероятность, что результатом агрегата станет такое значение, которое не могло быть ни в одном из "конечных" состояний базы, т.е. между транзакциями.

— ACID-изоляция; конкурентные транзакции не могут изменить твои данные; это может быть достигнуто исключительным доступом к таблице (блокировкой), либо же, транзакция, выполняющая агрегирующее чтение, будет работать с копиями данных, валидных на каждый момент их первого чтения на момент начала чтения; вот тебе пример того, что блокировки и уровни изоляции — совсем не одно и то же;

— откаты/обработка конфликтов; например, самостоятельный перезапуск базой запроса, если уже просмотренные данные были изменены конкурирующими транзакциями;

Первый случай еще обычно разделяют на два-три, по степени допущения несогласованности, но пример с агрегатом был взят именно затем, чтобы отличаться от "простой выборки".
Именно в этом месте "учебники по СУБД" нехило улыбают, бо я привел пример одной из самых распространнёных ошибок подсчёта агрегата и при неверно выбранном уровне изоляции.

В этом смысле разработчики СУБД дают прикладным разработчикам набор "ср-в" и умывают руки.
Мол, ты же сам виноват, что забыл защитить переменную мьютексом, как-то так. ))


S>Например, рассмотрите классическую задачу атомарного перевода денег между счетами, и убедитесь, что repeatable read достаточно для обеспечения согласованности данных в этой задаче.


Но недостаточно для моей задачи.
Если в рамках конкурирующей транзакции были изменены две строки данных, одну из них уже прочитали и подсчитали в агрегате, другую прочитали уже после фиксации — агрегат выдаст фуфел на выходе.


S>Если после чтения Дейта и Бернстайна не выходит понять, как так получается — почитайте Гарсиа-Молина или хотя бы Сьоре.


Ну да, вместо конструктива, вместо попыток понять конкретно обсуждаемый сабж, занимаешься пусканием "дымовой завесы".
Забавная тактика, за называние которой прямой речью тут банят. ))
Днище.



S>Поймите, бредовость вашего утверждения очевидна даже без копания в деталях


Какого именно утверждения?


S>если бы всё было так, как вы говорите, то никакие системы резервирования авиабилетов или банковской автоматизации не работали бы без "одного глобального мьютекса", что означало бы черепашью скорость проведения транзакций.


Ууу, как всё запущено. ))

Системы резервирования работают, внезапно, через различные допущения с целью того самого ускорения обслуживания.
Например, работавшая (не знаю как сейчас) еще с 90-х система резервирования ЖД-билетов работала через пулы, раскиданные по звездообразной схеме.
При исчерпании пула у локального и вышестоящего узла, резервирование порой выполняется ооочень долго.
Потому что чудес не бывает.

Ты бы эта хотя бы свои собственные примеры проверял, прежде чем приводить их якобы в пример якобы своей правоты.

А с современными скоростями интернета и быстродействием серверов и этого уже не требуется, ведь "один мьютекс" нужен не на всю базу ЖД-трафика, а на конкретный рейс, т.е., подозреваю, с пулами сегодня никто не возится, достаточно обеспечить fault tolerance, задача поиска свободных мест из десятков-сотен значений сегодня занимает микросекунды.

И да, при попытке фактического резервирования repetable read уже не катит, упс?
Re[96]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:

V>>Это адекватное решение и именно так СУБД работают.

S>Нет. Во всех СУБД, которые поддерживают row locking, блокировка строки и блокировка страницы делается через разные ресурсы, а не через один семафор.

Своим "нет" ты делаешь вид, будто подтверждаешь тезис из своего предыдущего поста, хотя ты говоришь о другом, т.е. твоё "нет" не относится ни к чему.

Будем разгребать:
Синклер:
— Неадекватное решение — реализация набора видов блокировок в СУБД через самописанный семафор, поддерживающий отрицательные значения счётчиков.

Я:
— твоё утверждение ложно, бо в СУБД широко используют именно самописные семафоры.

Синклер:
— нет, блокировка строки и блокировка страницы делается через разные ресурсы, а не через один семафор.

Я:
— а как соотносятся твои "разный" (в плане экземпляров) и "самописный"?
— и почему "блокировка" делается через "ресурсы"? ))

В общем, просьба не применять пока мест просто термин "блокировка", бо ты используешь его неверно уже десяток постов подряд.

Насчёт "ресурсов" буду считать, что ты оговорился.
Если нет — вот одна из первых ссылок в гугле, просто прочти первый абзац, там сходу понятно, что принято называть "ресурсом" в СМО:
https://cyberleninka.ru/viewer_images/16416395/f/1.png

Теперь возвращаюсь к самым первым рассуждениям, бо ты их лихо пролетел и у тебя не осело аж ничего.
В общем, еще раз чуть медленнее, как для самых маленьких:

Чтобы дойти до операции блокировки строки, ты должен сначала пройти уровень блокировки страницы.
Т.е. не заблокировать страницу, но "отметиться" на каком-нить примитиве сигнализации уровня страницы, и, отметившись удачно, запретить конкурентным задачам блокировать страницу. Т.е., shared-владение ресурсом запрещает блокировку ресурса (т.е. запрещает монопольное овладение ресурсом, а не производит это овладение, как может показаться из твоей ошибочной терминологии), т.е., чтобы заблокировать страницу, небходимо будет дождаться освобождения всех shared-владений.

В пред. абзаце выполняется ровно такой же шаг алгоритма, как в случае RO-RW блокировок.
Хотя ни о каком прикладном отношении RO-RW речь не идёт, речь идёт только о shared, либо монопольном владении, просто при shared-владении безопасны конкурентные чтения, вот и всё кино. Но всё это уже уровень прикладной семантики, т.е. интерпретирования состояний неких переменных, изменяемых атомарно.

В данном случае у некоей простейшей СМО (или простейшей такой подсистемы) есть всего два состояния — shared и exclusive.
Как обыграть эту пару состояний — я рассказал более чем доступно, ИМХО.

Но СМО (или её ячейка-посистема) может иметь более двух состояний.
Семантика состояний кодируется выбранным программистом образом, именно для этого я дал обобщённый код атомарного управления переменной самописного "примитива" синхронизации.
Если состояний будет более одного, их, например, можно будет закодировать в старших битах счётчика, и тогда код условия под if потребует наложения маски битового тела счётчика или еще каких проверок, согласно выбранной семантики закодированного значения.

Не зря я в самом начале предложил абстрагироваться от идентификаторов блокировок, а просто пронумеровать их, связав в иерархию, чтобы не засорять моск ненужной информацией.
Точно так же можно абстрактно пронумеровать состояния СМО и построить граф премещения по состояниям.

Стадия анализа задач, про которую я уже совсем не скромно намекаю который пост подряд, должна дать тебе отображение прикладных требований на выбранную схему СМО, адекватную поставленной задаче, включая графы переходов, если состояний более одного. Далее просто кодируются (нумеруются) уровни иерархий, состояния и дуги-сигналы, и затем накладываются те механизмы реализации схемы, о которых я завёл речь с самого начала.


И да, просьба заканчивать буксовать на "единственном семафоре", бо в подробном описании различных алгоритмов RO-RW блокировки ключевой семафор я называл целевым, но никогда не было речи о том, что один семафор может обслужить разные уровни иерархии, если есть такая потребность в разных уровнях. Один он будет на своём уровне.

К тому же, достаточно того, что упоминался "турникет" — а это семафор со счётчиком 1, где "турникетом" его делает способ оперирования этим семафором. Т.е. уже минимум два семафора. И еще требуется сериализация писателей, если есть желание решить проблему голодания писателей в случае, когда мы не управляем задачами, а пользуем семафоры уровня ОС — уже 3 семафора. И это только для разруливания проблематики совместного или монопольного доступа к одному ресурсу.

А ресурсы у тебя иерархические, как матрёшки, и в точности такая же задача возникает на каждом слое матрёшки — об этом было сказано вообще сразу и шло как контекст.
(при переходе от таблицы к странице, до этого при переходе от базы к таблице, до этого на уровне схемы)

И я уже напоминал, что различные уровни изоляции достигаются не только и не столько за счёт блокировок, а чаще за счёт алгоритмов, растущих из банального COW.
Т.е., на некоторых уровнях изоляции конкурентные чтения и даже транзакционная запись может быть, но совершенно без эксклюзивных блокировок "ресурсов", как тебе такое?

И да, в прошлый раз было лень пошариться по и-нету, вот ответ на твои странные вопросы из разряда "а зачем вы рассматривали семафоры ОС и свои самописные, зачем рассуждали об адекватности?"
Сорри, но подобного рода "вопросы" вызывают у меня культурный шок.



S>>>Неадекватное оно по вашим же словам.

V>>Это ты придумать изволишь.
S>Цитирую:
S>

S>Одно но — на многопроцессорной машине в режиме вытесняющей многозадачности наших "очередей" нет, есть очереди уровня ОС, поэтому возможно голодание писателей, т.к. даже при ограничении доступа к ресурсу счётчиком 1, его могут захватить конкурентные потоки-читатели.


1. Где конкретно здесь про адекватность моего решения?
Это про адекватность дефолтного.
Если ты хотя бы из банального любопытства никогда ранее не интересовался алгоритмом RO-RW блокировки, то мог бы найти и ознакомиться на многих углах в инете.

А недефолтные алгоритмы — сплошное ноу-хау, увы.
И почему так — именно тебе не так давно рассказывал уже.


V>>Было показано:

V>>http://www.rsdn.org/forum/flame.comp/8108567.1
V>>И там же ты оставил мой процитированный псевдокод, который позволяет добавить к семафору произвольную операцию.
S>После добавления к семафору "произвольной операции" придётся ещё допилить код выбора между продолжением и ожиданием.

Пфф, очередной культурный шок.
Коду вообще требуется, чтобы его кто-то писал.

Выглядит как когнитивный диссонанс по причине "само не работает".
Т.е., на уровне мозжечка привык рассуждать в духе "с неба упало и само работает", вот до чего дотнет доводит. ))

Только в твоём случае этот феномен доходит до крайности: "обычные люди это сделать не смогли бы, такие как я или любые мои собеседники в интернете".
Отсюда твоя неприятная нервозность и низкий конструктив.


S>В вашем простом примере acquire() полагается на то, что одиночный release освободит достаточно ресурсов для успешного захвата, поэтому после _sema.acquire() можно просто выйти.


В том моём примере счётчик может быть отрицательным, как ты просил показать.
И это требуется для более простого решения задачи про СМО из двух состояний: совместного или исключительного доступа к ресурсу.

Плюс я приводил пример сигнатуры release семафора в Windows АПИ и дотнетных реализациях — у всех за раз можно "освободить" более единицы, т.е., семафоры не обязательно инкрементируют только на единицу. Через отрицательный счётчик ввел еще возможность декремента на произвольное число для надобности описанного алгоритма.
И вообще дал возможность проводить любые вычисления с счётчиком в атомарной манере.

В общем, странно, что эти простейшие телодвижения вызвали у тебя настолько серьезное заклинивание. ))
Не высыпаешься совсем?


V>>Показано.

S>Где? Никакого кода, кроме простейшего легковесного семафора поверх семафора ОС, не приведено.

Этим я ответил на то, про что ты громче всего кричал на той стадии.
Чтобы перейти к следующему вопросу, надо проехать хотя бы этот.
Потом проблематику RO-RW.
Потом обнаружить, что ключевым является управление дисциплиной захвата ресурса, т.е. наличие более одного состояния простейшей одной ячейки СМО.

А у тебя ресурсы вложены аки матрёшки...
А потом, я надеялся, что в этом месте тебя осенит и ты перестанешь задавать неконструктивные вопросы.

V>>И рассказано, что если управлять задачами самостоятельно, то от семафоров уровня ОС можно будет отказаться, по крайней мере в алгоритмах управления задачами, оставив системные семафоры только на случай, когда рабочим потокам нечего делать, чтобы иметь возможность их пробуждать (это я уже повторяюсь, бо ты невнимателен).

S>Я вполне внимателен, просто вы пишете много банальностей и мало кода.

Для тебя не банальности, раз ты буксуешь, та еще так громко.
Я пока не убедился, что ты понял хотя бы описанный мною алгоритм.
И тем более не убедился, что ты понял, как такие алгоритмы вообще разрабатывают — задачи-то разные бывают.


V>>Как код реализации СУБД? ))

S>Именно.

Но ты же не мог всерьёз просить меня ответить тебе работающими исходниками полноценной СУБД? ))
До такого маразма, я надеялся, не дойдёт, поэтому списал на обычную твою нервозность.
И сейчас списываю.


S>Напомню: мы обсуждаем реализацию гипотетической СУБД, которая должна быть эффективнее существующих.


С херна ли эффективнее существующих?
Кто тебе такое обещал?

Мы обсуждаем как оно устроено и работает.
Обсуждение возникло по причине того, что ты злостно путаешь уровни изоляции и "блокировки".

На первой стадии я вполне внятно продемонстрировал, что будучи организованым только поверх примитивов синхронизации ОС, оно будет неадекватно задаче.
А будучи реализованным через ручное управление заявками, можно подключать наработки из СМО — они туда сам просятся и так, вообще-то, и поступают при разработке подобных систем сложных диспетчеризаций заявок.

Не только СУБД.
Я с IP-телефонией одно время имел, там те же СМО, очень похожие задачи.
Твоё зацикливание на СУБД говорит лишь о том, что ты не понимаешь сам этот класс задач.


Возвращаясь ко встроенным примитивам синхронизации — дело не только в дороговизне вызовов АПИ ОС поверх защищённой памяти, еще я раскрыл проблематику турникета, и, вроде бы, вполне однозначно, понять неверно там просто никак.

Еще тебе говорилось, что вместо "различных видов блокировок" (как ты рассуждал в начале этой беседы), стоит оперировать не их именами собственными, а достаточно рассматривать их нумерованную иерархию, бо на каждом уровне иерархии в плане отношений с низлежащим слоем в СУБД соблюдается строгое подобие от уровня выше.
(не всеми уровнями иерархий доступно одинаково развитое управление извне, но "унутре" отношение сущностей одинаковое).


V>>Ты опять задаёшь вопросы не по существу, в рамках обсуждений форума мы можем рассмотреть лишь отдельные моменты, но ты и их понять и продвинуться на шажок дальше пока не в состоянии.

S>Мы сможем двигаться дальше, если вы будете приводить код, а не абстрактные рассуждения про СМО и симуляцию.

СМО — это не абстрактные рассуждения, а вполне конкретные, и сразу же было сказано почему — так УДОБНЕЙ.
Удобней разрабатыать модель, удобней её реализовывать, и эта реализация более адекватна, чем на доступных изкаробки ОС ср-вах.

Про симуляцию — тем более.
Да, просимулировать происходящее можно и на обычных семафорах, в т.ч. используя код того полусамописного семафора, который я дал, т.к. при симуляции обычно не интересует быстродействие эмулятора, интересует происходящее в количественном выражении, т.е., где, какие, сколько операций, какова вероятность/статистика развития тех или иных сценариев из большого комбинаторного их сочетания и т.д. и т.п.

Модель может быть хоть самой тормознутой, от модели требуется быть удобной для программирования/оперирования/развития-модификации.

В общем, мяч пока на твоей стороне, уже ты должен приводить код, хотя бы чтобы продемонстрировать своё понимание.
Где у тебя возникнут сложности — я помогу, как помог с этим семафором, не переживай. ))


V>>Это ты опять невнимателен.

S>Мне цитату привести?

Да, и еще раз да.
Заодно сам еще раз внимательно перечитаешь.


V>>Ну так и перепроверил бы себя, что именно утверждалось.

V>>А то мне на каждый абзац здесь руку-лицо ставить надо.
S>Ок. Цитируем:
S>

S>В отсутствии конфликтов — одна интерлокед-операция на таблицу для скана таблицы.
S>Считай, бесплатно.


И?
Одна на таблицу.
До этого одна на базу.
До этого одна на схему.
До этого минимум одна на входной механизм самописных очередей задач.
До этого на пул запросов, на ресурсы, требуемые для работы хотя бы парсера и валидации SQL, составления плана запроса согласно текущей схемы базы и т.д. и т.п.

Но в дефолтном алгоритме RO-RW блокировки аж три семафора, три недешёвых вызова АПИ ОС только на реализацию всего двух состояний СМО всего одного уровня из иерархии.
Разве не ого? ))

А если состояний "ячейки" СМО более одного (как ты там упоминал еще виды блокировок) — то и вовсе по-дефолту обычно делают на условной переменной, со всеми её suspicion wake up и чудовищной вероятности столкновения потоков на единственном мьютексе, обслуживающем эту условную переменную.


V>>Чтобы осмысленно возражать, тебе сначала придётся показать, что этот алгоритм не отвечает задаче переключения дисциплины обслуживания ресурса.

V>>И что-то мне подсказывает, что как только ты попытаешься это показать, т.е. включишь моск, многие вопросы отпадут сами собой.
S> Показываю на пальцах: Допустим, у нас уровень параллельности = 8. Разделяемые блокировки на ресурсе реализуются как acquire(1), эксклюзивные — как acquire(8).
S>Блокировки строки — опять же, acquire(1), страницы — acquire(8).

8 будет если на данном уровне иерархии ровно 8 фактических shared-владений.
А если одно?
А если ни одного?
Ты там цикл не видел разве в псевдокоде обновления счётчика?


S>Транзакция A продолжает работу, захватывает shared lock на записи номер 4, 5, 6, 7, 8, 9, 10 при помощи Page(42).acquire(1) — успешно.


Зачем?
Ты ведь уже shared-владешь страницей, т.е. можешь читать данные этой страницы "просто так".
Это тогда надо заходить на страницу под другой дисциплиной блокировки, например, "я могу блокировать с разными дисциплинами произвольные твои строки конкуретно", и тогда страница не пустит shread-RO "клиентов" к себе.

И тогда acquire ты будешь запрашивать у конкретной строки, а не страницы, бо на страницу под нужной тебе прикладной дисциплиной ты уже вошёл.

Или, при реализации COW, если страница захвачена читателями и для тех уровни изоляции позволяют, твоя транзакция может поступить иначе — сделать копию страницы, обновить строки в этой копии, а потом обновит цепочку страниц (про COW тебе тоже говорилось сразу).

А текущая страница для shared RO-заявок переходит в режим фантома и будет жить до тех пор, пока ею shared-владеют, потом тихо умрёт.


S>Хотим захваттить shared lock на запись №11. Упс — кончился уровень параллелизма, встаём в дедлок


Здесь опять путаешь уровни иерархий.
Говорил же тебе — тупо пронумеруй, меньше вероятность ошибиться. ))


S>Нет, так нельзя, надо увеличивать уровень параллелизма до MAXPAGERECORDS.


В системе с хаотическими заявками из хаотичных потоков может и надо, смотря как реализовано.
Но тогда привет турникетам и база быстро встанет колом, при таком-то кол-ве уровней иерархии.


S>В общем, предлагаемый вами механизм заведомо неполон.


В общем, я пока не вижу понимания даже на 10%.
Мне пока кажется, что ты уже понял про "гибкий" семафор, твой тон в этой области снизился, будем считать это за признаки понимания, ОК.

Надеюсь, на следующей итерации у тебя будет получше с пониманием целевого — а зачем вообще требуется нетривиальная возня с режимами СМО.

И важное про уровень параллелизма.
Тут ты еще напутал сами ресурсы.
Про уровни параллелизма когда речь, то ресурсом является вычислительный блок, (процессор, ядро, поток в ядре и т.д., смотря как железка устроена).

Например, транзакция, выполняющая COW, делает обновления многошагово, т.е. через последовательность заявок.
Первая заявка иницировала транзакцию, произвела первое чтение.
Если были конкуретные чтения или даже чтения-записи, то в рамках транзакции могут создаваться копии данных, как упомянул выше. Одна операция чтения — один уровень параллелизма (допустим для простоты). В системах с отказами и последействиями, например, нужной страницы нет в памяти, — будет отказ и новая постановка в очередь с новым состоянием заявки (см эту категоризацию СМО, сама эта категоризация даёт много подсказок).

Т.е., диспетчер одного "физического" потока может рассматривать в т.ч. "параллельную" очередь заявок, беря на исполнение те, к которым к требуемым ресурсам есть доступ (список ожидаемых ресурсов, в свою очередь, может представлять из себя круговую очередь).

Освободили "ресурс", т.е. процессор-ядро-поток, исполняем следующую заявку. Вполне может быть, что следующей будет заявка из той же самой транзакции, она ведь при инициализации могла накидать сразу пачку заявок, т.е. вероятность последовательного расположения заявок от одной транзакции будет высокой.


S>Его можно допилить до требуемого уровня функциональности, но, повторюсь уже в третий раз, вы получите ровно те же блокировки, которые мы наблюдаем в промышленных СУБД.


Не, мистер Блейн, с "промышленными" СУБД я не спорил, я тебе их объясняю, бо ты путал блокировки и уровни изоляции.
Я отделяю для тебя мух от котлет.

В общем, тебе придётся найти подтверждение этой (уже не первой) инсинуации или прилюдно извиниться.


S>И их виды, и их иерархию. И код исполнения запроса будет точно таким же, как у всех — внутрь цикла сканирования мы будем вставлять вызовы _lockManager.AcquireSharedLock(_rowID).

S>Если вы попробуете на коленке набросать код этого метода, то поймёте, о чём я говорю.

Ага, т.е. я прав — ты теперь пытаешься замылить саму суть обсуждения, как обычно ища виноватых в своем непонимании на стороне. ))

Рановато, мистер Блейн, фокус не удался.
"На коленке" я жду от тебя куда как более примитивную часть этого кода — простое управление shared-exclusive доступом ко всего одному ресурсу, т.е. очень простой СМО из двух состояний.

И жду понимание того, как с помощью аналогичных механизмов, раскиданных по разным уровням иерархий, реализовать комбинаторику возникающих сценариев при организации различных уровней изоляции.

И тогда ты будешь готов согласиться с самыми первыми моими заявлениями, насчёт простой нумерации уровней иерархий.
Пока что ты от этого слишком далек.


V>>Заведомый ACID можно обеспечить исключительно и только одним глобальным мьютексом, через сериализацию доступа.

S>Ну конечно же нет.

Ну конечно же да.
Потому что в какой-нить транзакции я могу по некоему условию менять даже схему таблиц, т.е. заранее неизвестно.
И тогда ACID на всех уровнях, кроме сериализованного не будет соблюдаться от момента начала такого участка транзакции, т.е. базе придётся войти в сериализованный режим.

А всего-то самый верхний уровень иерархии, никаких тебе эзотерических рассуждений с придыханиями.


S>Почитайте любой учебник по СУБД.


Опять мимо, тут нужен учебник не для пользователя СУБД, а для разработчика СУБД (угу, не разработчика прикладной базы данных, а самой СУБД).
СМО — неотъемлимая часть такого учебника.


S>Вас не настораживает, что блокировочники на уровне изоляции serializable не делают один глобальный мьютекс на базу?


Это смотря что транзакция делает, т.е. на каком уровне иерархии работает.
Exclusive lock на уровне конкретной таблицы — это та самая сериализация доступа к этой таблице.


S>Глобальная блокировка является достаточным, но вовсе не необходимым условием для serializability.


Опять та же ошибка — зависит от уровня иерархии оперируемой сущности.
Еще раз — пронумеруй, будешь меньше путаться.


V>>Требуется, наоборот, обеспечить уровни изоляции худшие, чем сериализованный, с целью увеличения уровня конкурентности системы.

S> Для начала разберитесь с serializable.

Не прокатило.
На данной стадии ты можешь или тихо слиться, или взять себя в руки, наконец, и разобраться с предметной областью.
Она не слишком сложная, в сети мильон конспектов лекций.

СУБД тут ни разу не уникальны, т.е. до смешного — сама попытка отослать к учебнику по некоей СУБД демонстрирует не просто непонимание предметной области, а отсутствие простой "записи" в эрудиции о наличии самой предметной области.


V>>Это если ты верно используешь термин "блокировка" в IT, где этот термин подразумевает исключительное владение ресурсом.

S>В СУБД блокировки бывают не только исключительными. Блокировка означает некоторую степень владения ресурсом.

В английском различают термины lock и block, в русском языке возникает путаница.
Поэтому, стоит использовать или английскую терминологию, или длинную русскую, навроде "блокировка для совместного доступа по чтению".

В русскоязычном IT "просто блокировка" означает blocking lock на английском.


S>Далее, вам нужно повторно изучить раздел "изоляция транзакций" в более-менее любом учебнике, и разобраться, почему "допущения, ухудшающие ACID", не обязательно приводят ни к несогласованности, ни к отказам/конфликтам.


"Не обязательно" не канает.
Речь же о статистике-вероятности.

На пальцах — ты можешь забыть защитить изменяемую из разных потоков переменную мьютексом, но это не обязательно приведёт к конфликтам-несогласнованности.
Как карты лягут.

Простой пример:
вот у тебя запрос с агрегацией только по чтению.

Какие могут быть уровни изоляции:
— никакой, т.е. код исполнения запроса читает и те данные, что уже есть и те, что были изменены; есть вероятность, что результатом агрегата станет такое значение, которое не могло быть ни в одном из "конечных" состояний базы, т.е. между транзакциями.

— ACID-изоляция; конкурентные транзакции не могут изменить твои данные; это может быть достигнуто исключительным доступом к таблице (блокировкой), либо же, транзакция, выполняющая агрегирующее чтение, будет работать с копиями данных, на момент начала чтения; вот тебе пример того, что блокировки и уровни изоляции — совсем не одно и то же;

— откаты/обработка конфликтов; например, самостоятельный перезапуск базой запроса, если уже просмотренные данные были изменены конкурирующими транзакциями;

Первый случай еще обычно разделяют на два-три, по степени допущения несогласованности, но пример с агрегатом был взят именно затем, чтобы отличаться от "простой выборки".
Именно в этом месте "учебники по СУБД" нехило улыбают, бо я привел пример одной из самых распространнёных ошибок подсчёта агрегата и при неверно выбранном уровне изоляции.

В этом смысле разработчики СУБД дают прикладным разработчикам набор "ср-в" и умывают руки.
Мол, ты же сам виноват, что забыл защитить переменную мьютексом, как-то так. ))


S>Например, рассмотрите классическую задачу атомарного перевода денег между счетами, и убедитесь, что repeatable read достаточно для обеспечения согласованности данных в этой задаче.


Но недостаточно для моей задачи.
Если в рамках конкурирующей транзакции были изменены две строки данных, одну из них уже прочитали и подсчитали в агрегате, другую прочитали уже после фиксации — агрегат выдаст фуфел на выходе.


S>Если после чтения Дейта и Бернстайна не выходит понять, как так получается — почитайте Гарсиа-Молина или хотя бы Сьоре.


Ну да, вместо конструктива, вместо попыток понять конкретно обсуждаемый сабж, занимаешься пусканием "дымовой завесы".
Забавная тактика, за называние которой прямой речью тут банят. ))
Днище.



S>Поймите, бредовость вашего утверждения очевидна даже без копания в деталях


Какого именно утверждения?


S>если бы всё было так, как вы говорите, то никакие системы резервирования авиабилетов или банковской автоматизации не работали бы без "одного глобального мьютекса", что означало бы черепашью скорость проведения транзакций.


Ууу, как всё запущено. ))

Системы резервирования работают, внезапно, через различные допущения с целью того самого ускорения обслуживания.
Например, работавшая (не знаю как сейчас) еще с 90-х система резервирования ЖД-билетов работала через пулы, раскиданные по звездообразной схеме.
При исчерпании пула у локального и вышестоящего узла, резервирование порой выполняется ооочень долго.
Потому что чудес не бывает.

Ты бы эта хотя бы свои собственные примеры проверял, прежде чем приводить их якобы в пример якобы своей правоты.

А с современными скоростями интернета и быстродействием серверов и этого уже не требуется, ведь "один мьютекс" нужен не на всю базу ЖД-трафика, а на конкретный рейс, т.е., подозреваю, с пулами сегодня никто не возится, достаточно обеспечить fault tolerance, задача поиска свободных мест из десятков-сотен значений сегодня занимает микросекунды.

И да, при попытке фактического резервирования repetable read уже не катит, упс?