Странное конструктивное решение для колёс. Да ещё и с бортиком. Неужели сразу не понятно что это идеальное место для мусора? А всего то надо было убрать бортик и сделать внутреннюю поверхность под углом наружу.
Ну или рёбра жёсткости добавить на внутреннюю поверхность в виде скошенных наружу линий. Получится бы своеобразный винт при движении которого всё бы вышвыривалось. Вон в протекторе на шинах так и делают для вышвыривания воды из под шины. Там даже есть параметр сколько литров за единицу времени. И величине этой позавидовали бы самые крупные насосы.
Как то раз в жизни тоже приходилось заниматься таким шитьём. В бедные 90 годы, имея на руках единственный компьютер (вроде PII) на котором был спален 1 COM порт. А мне для экспериментов нужны был 2 штуки. Под подозрение попала мохнатая микросхема всей периферии, ног наверно на 150.
Найдя донора но в другом форм факторе, с «трясущимися руками» и надеждой не убить окончательно единственную рабочую машину, я всё же решился на пересадку.
В результате на мат плате нарисовался похожий ёжик, как в статье. И какая же была радость когда работал и LPT — через который я программировал, и заработали оба COM порта. Ностальжи…
Во времена спектрумов у меня был аналог. При включении в ПЗУ находился интерпретатор бейсик. И всё.
И что бы поиграть, мне приходилось писать простенькие игры. Карточные, змейки, стрелялки и прочее… Запускать, играть. После выключения всё удалялось. В следующий раз всё по новой ))))
Глянул статью и увидел классную картинку из классной книги, которую мне посчастливилось в детстве получить. Ностальгия… Ещё там был крутой компьютер нарисован в виде ноутбука. Раскроешь книгу — и представляешь как будто за реальным компом сидишь.
Неправда. Во первых никогда не бывает абсолютных утверждений. И это абсолютно. Шутка.
Во вторых. Например я никогда не оставляю код с предупреждениями. И в 99% случаях они правильные. Но всегда есть нестандартные случаи. Например навскидку:
Компилятор C# всегда ругается на не инициализированные переменные. Но проблема в том что он не смотрит вглубь кода больше чем на 1 уровень. И если инициализация будет после двух if — он этого не увидит.
Опять же у меня в практике был случай когда статические классы инициализировать через рефлексию — тоже была ругань. Ну и так по мелочи.
Опять же если речь про C# — то это живой язык и там чуть лине через день прилетают обновы. И порой прилетает такое — что вполне рабочий код становится жёлтым на половину. А всё потому что решили ввести новое предупреждение — не помню что, что то с null связано было. Пришлось отключать это через настройки глобально.
Вся проблема в том что естественный язык он общий. А в программировании приходится описывать все случаи.
Например есть человеческая фраза: «Не лезь в розетку — убъёт!»
В программировании будет выглядеть так:
Не лезь в розетку — убъёт!
ЕСЛИ ты электрик — то можешь лезть
ЕСЛИ в розетки есть напряжение 220 и ты электрик — не лезь
ЕСЛИ ты электрик но в перчатках — то лезь
ЕСЛИ напряжении 10kV и ты в перчатках — не лезь
ЕСЛИ напряжении 10kV и ты используешь клетку Фарадея и специальный уравнивающий щуп…
И т.д. миллион вариантов
Что бы не писать миллион букв (привет бейсику )) просто всё заменяется на X,Y,Z и прочие переменные, а условия на операторы if,for и другие.
И вуаля! Получаем язык С. На котором удобно писать программы и понимать их. И не нужны никакие прослойки.
Тоже хотел написать про это. Процы в видеокартах нередко работают при температуре выше 100С и выделяя мощность на квадратный сантиметр раз в 10 больше чем сопло ракеты.
А с радиацией я вообще не понял взаимосвязь. Она разрушает процы путём открытия двух противополярных комплементарных транзисторов которые образуют КЗ. И собственно проц разрушает не сама радиация, а короткое замыкание и в следствии разрушительное выделения тепла. И современные радио-стойкие процы, они радио-стойкие не потому что какие то другие материалы используются, а потому как схема там строится так что бы отлавливать такие КЗ и отключать эти участки, что бы сами себя не поджарили.
Может взаимосвязь в том что новый метериал выдерживает больше температуры (300C)? Но кз нагревает локально участки до тысячи градусов.
Да я про это и пишу же. Вся проблема в размере массива, а именно таблицы. А они и на миллиард бывают строк. В этом случае надо на те же пару миллиардов служебных колонок зависти.
Плюс делать не одну простую проверку за цикл, а как минимум 3 — на предмет удаления строки, на предмет новой строки, на предмет изменения данных. И это только что всплыло в обсуждении. Что там ещё при разработке всплывёт?
Это я не упоминаю про индексы. Это те же самые массивы. Для них тоже придётся всякие служебные колонки вводить. И вообще непонятно что будет с раздвоенным индексом, в варианте вставки/удалении строк.
Я не говорю что идея плохая. Просто в представленном виде она имеет критичный оверхед. Но зерно в ней есть, надо подумать над ней, может получится усовершенствовать.
Поразмыслив над вашей идеей всплыло куча подводных камней.
Например как учитывать новые добавленные строки? В старой таблице не будет этих строк и собственно не будет 4-го поля для анализа.
Как учитывать удалённые строки? Это придётся ещё тогда служебный столбец добавлять типа deleted. И его тоже анализировать при каждом цикле?
Одновременно транзакция write может работать только 1. Потому как на каждый write придётся дублировать все эти поля.
Понял вашу идею.
И что получаем. На каждый цикл проверки делать дополнительную проверку 4 поля. И того если имеем миллион строк. Проверок делаем 2 миллиона при переборе (в случае когда условие например придётся на последнюю строку). А если учесть что это будут if с переходом — то скорее всего поломается оптимизация в проце для чистого перебора массива.
Далее мы должны в каждой таблице загруженной в RAM делать дополнительную колонку — например int. И того на 1M строк имеем лишние 4Mб данных.
Меня больше всего волнует потеря производительности для двойной проверки каждой строки.
БД про которую я пишу это не in-memory БД. А работает на страницах. Но в любом случае, если таблица без индекса — то её нужно будет загрузить всю в RAM — где в цикле проверять каждую строку. Если памяти не хватает — придётся выгружать первые страницы(которые уже не нужны) из RAM, пред загрузкой последних.
То что вы описали — это то что описал и я. В цикле для каждого столбца каждой строки придётся вызывать функцию которая будут проверять изменялось ли значение. Проверка это будет в общем случае как перебор другого массива в котором будут например структуры (номер строки, номер столбца, новое значение). И избавится от этого дикого оверхеда не получится.
Понятно про что вы пишете. Вопрос в том имеет ли это смысл, Смотрите — самый простой, и самый быстрый вариант хранения таблицы в памяти — одномерные массивы массивов. Тогда SELECT без индекса — это просто for по массиву. Он делается максимально быстро в кеше процессора.
С другой стороны имеем тот же массив массивов + новые изменённые данные. Где их хранить? Ну допустим имеем новый массив. В котором например структуры (номер строки, новое значение). Тогда вместо простого for, мы должны на каждом цикле делать запрос к новому массиву, перебирать его и искать изменённую строку. Получаем дикий оверхед. Как избавится от этого оверхеда? Так на вскидку ничего нормального в голову не приходит. А если изменений на гигабайт — то вообще получим неработоспособную систему — такой SELECT просто зависнет навечно.
И тут получаем мой вопрос — а ради чего это нужно?
Пока напрашивается простой вариант — сделать 2 вида транзакций:
Fast — это в которых нету внутренних select, либо нас устраивают устаревшие данные. В таких транзакциях блокировать таблицу в конце транзакции.
И второй вариант — с полной блокировкой таблицы.
Что касается собственной разработки БД.
По поводу преимуществ собственной разработки уже были да и будут миллион дискуссий, более того всё существующее ПО это когда то собственная разработка. Но я согласен — без явной причины, на такой подвиг я бы не согласился ни за что. Нас вполне устраивал Postgres. Тут мне в личку писали, я там подробно ответил причину почему всё таки своя БД. Приведу ответ тут:
По поводу БД. Решение написать свой велосипед был непростым, но ему предшествовала 1 причина. Изначально БД была MSSQL, давно правда, потом перешли на Postgres. И он собственно устраивал на 100%. Но как то в 1 момент на 1 из проектов вылез непонятный косяк. Postgres периодически рандомно подвисал на транзакциях. Проблему искали 3 месяца. Что только не делали. Обложили всё что можно логами. Postgres заставили выводить все логи которые он может. Но блин из логов было только что мол этот запрос выполняется 40 секунд. Почему — хрен знает. Даже написали свой провайдер (до этого был Npgsql), думали проблема с коннектами.
А причина потом оказалась до банального проста. Кабель соединяющий один из RAID дисков — подгнил и периодически глючил. И postgres — просто периодически висел в ожидании записи на диск данных в WAL. И НИГДЕ ПРО ЭТО НЕ писал.
Собственно боязнь очередной нерешаемой подставы — привёл к решению собственной БД. Где можно посмотреть ВСЁ.
БД сейчас в стадии разработке. Используется C# и .net core. Для нас такое решение идеально потому как позволяет применить 1 интересную вещь. БД используется для web платформы, которая тоже написана на C# и .net core. БД — встраиваемая (вариант автономной работы тоже закладывается). И в режиме встраивания можно объединить обработку запроса в web сервере и БД в 1 поток с одним адресным пространством. Написал сумбурно — но смысл прост, уберется прослойка в виде TCP соединения с базой данных, и достигается максимальное быстродействие. И главное работа с БД у нас построена на процедурах. Писать процедуры на языке SQL — тот ещё геморрой, но мы привыкли уже. В нашей же БД процедуры пишутся на C#. NET вообще замечательная платформа. Лучшая по отладке. Например типичный кейс — приконектится из windows к серверу linux на другой стороне шарика к рабочему процессу в режиме отладки и у себя в студии просто по шагам отлаживать в исходном коде, с просмотром переменных и прочего. Иногда только так можно найти баг, который у тебя в локальной среде не воспроизводится.
Сейчас БД находится в стадии разработки. Например изначально был только управляемый код, что бы отладить основные механизмы. Сейчас переписываться под неуправляемый — что бы получить скорость. Разработки ещё на год…
Параллельно пишется менеджер для работы с БД. По типу SQL Manager for PostgreSQL. Тоже непростая вещь.
В дальнейшем планируется выложить БД в opensource. Но пока рано.
SCN — у нас тоже пару раз мелькал в обсуждениях. Ничего сложного нету что бы сделать какой нибудь long и инкриментировать его в транзакциях. Вот только куда и зачем это применить так и не нашлось. И главное это ни как не решает проблему которую я описал. А именно где хранить изменения которые произошли внутри транзакции — напрямую в таблицах RAM или в другом месте. А в таблицы данные переносить при выходе из транзакции. И в этот момент уже точно — хочешь не хочешь а таблицу придётся блокировать. Нельзя вносить одновременно изменения в один массив (таблицу) из разных потоков. Иначе такая каша может получится. Типа в одном потоке мы удалили строку, а в другом вставили. А в реальности существует строка или нет будет решать рандом переключателя задач.
Выигрыш записывать изменения в конце транзакции только в том что это время будет меньше чем время всей транзакции.
В нашей БД такой механизм применить легко даже не сильно меняя код. А именно. При каждом INSERT/UPDATE/DELETE — идёт запись в WAL. Так вот просто комментировать строку изменения таблицы, при этом изменения WAL останется. А в конце транзакции применить WAL к таблицам. Точно также как WAL применяется при старте БД. Также решается мега геморрой отката транзакции — его просто не будет, потому как таблицы RAM не изменились.
Но тогда внутри транзакции SELECT будет работать на устаревших данных.
И ещё непонятно. При старте транзакции указывается список таблиц которые должны быть неизменны на момент старта транзакции, транзакция же атомарна, что бы вся логика внутри транзакции отработала правильно. Но в случае если не блокировать таблицы — и изменения в них могут вносить другие транзакции, может получится каша.
Например делаем внутри транзакции SELECT сколько денег у клиента. Возвращается что 100$. Далее идём делать какую то логику. А в этот момент в другой транзакции снимаем эти 100$. Но при этом мы находимся в первой транзакции и она работает по логике что у клиента есть 100$.
Короче есть на чем подумать. Если внутри транзакции ненужны селект — то можно не блокировать таблицы на время транзакции. В сценариях описанных выше — такой подход неприемлем.
С вами согласен. Пост просто пролистал и сразу перешёл к комментам.
Но по поводу страниц хотел бы сказать зачем мы их применили у себя. Не буду описывать тернисты путь, как мы выбирали размер и прочее, напишу 2 главные причины.
Страницы на диске по 8Кб — основная причина, если мы изменили 1 байт в таблице, не хотелось бы переписывать 16Мб на диске, если страница например 16Мб. Изначально такой размер был выбран для получения преимуществ в скорости чтения с диска, и количества файлов в файловой системе, которое тоже ограничено, и прочего. Но последующая разработка показала оптимальным всё таки размер совпадающий с размером странице диска.
Страница в RAM — тоже равна 8Кб. Основная причина — экономия RAM. Загружать в RAM только те страницы которыми пользуешься.Опять же если страница RAM и DISK одинакового размера — то упрощает их синхронизацию.
Тут надо различать как бы 2 БД. 1 находится в виде файлов на диске. Другая загруженная в RAM. Как раз вся работа с БД идёт в RAM. А на диск уже идёт только синхронизация.
И Вакуум запускается для диска. Потому как на диске используется страничная организация памяти.
А вот для RAM — там можно безнаказанно выделять и удалять память. Иначе можно вставить гигабайт данных, а потом удалить. И что этот гигабайт будет висеть мёртвым грузом в RAM?
Но я не знаю как точно работает postgres. Я написал как это должно работать по логике.
В разработке сейчас собственная реляционная табличная БД. Причина собственной разработки это отдельная тема. И честно сказать — это самый мозговыносящий проект в моей практике.
Прочитав ваш комментарий я прекрасно удивил одну из проблем которую мы решали в процессе проектирования. И у меня возник вопрос.
Собственно как работает доступ к таблицам. Разные потоки делают запросы на read — при этом таблица лочится — но все могут получить доступ на чтение. Если в очереди запросов подходит запрос write — то ожидается пока все read не закончатся, потом лочится на write — и далее с таблицей работает 1 поток.
Все INSERT/UPDATE/DELETE — это write запросы и делаются внутри транзакции. И представим ситуацию — мы сделали UPDATE на гигабайт данных, или DELETE — а далее делаем SELECT в тойже транзакции — и мы должны получить уже изменённые данные. Самое простое — это когда мы залочили таблицу и делаем изменения прямо в ней. И Select тоже в ней. Если придётся откатывать транзакцию — то это тяжёлая операция. В нашем случае — идёт восстановление таблицы из журнала WAL. Также при откате Текущий WAL транзакции не записывается на диск.
Вы же описали ситуацию когда изменения INSERT/UPDATE/DELETE не делаются в существующие таблицы, а делаются кудато в другое место. Ну допустим в массив какой-то. Соответственно в это время с таблицей могут работать другие в режиме read.
Но как тогда делать SELECT? Путь это простая таблица без индексов. Это будет набор массивов в котором просто циклом перебираем строки. Но в вашем случае надо как то знать какие строки изменённые.
Конечно можно придумать геморройный механизм этого. Но это будет намного медленнее и жрать память. Простой перебор одномерного массива намного быстрее, чем перебор с проверкой — а не изменилась ли строка? А ещё надо учитывать DELETЕ — который может вообще пол таблицы в разных местах выкинуть.
Вобщем вопрос — а нужно ли такое поведение? Я вижу как минимум например засаду в следующем сценарии. Сделали платёж — запустился скрипт изменения баланса в БД — но подавис по времени. Если сделать сразу новый платёж — то мы получим неправильный баланс денег.
Запомнился один случай из многолетней практики. Запускаю код и он неожиданно выдаёт правильный результат сразу. Что меня очень удивило. Начал разбираться и оказалось — правильный «результат» был выдан потому что тот код который должен был быть протестирован, до не го даже не дошла программа. Не работала та часть которая уже вроде была оттестирована и должна была работать правильно.
Ну или рёбра жёсткости добавить на внутреннюю поверхность в виде скошенных наружу линий. Получится бы своеобразный винт при движении которого всё бы вышвыривалось. Вон в протекторе на шинах так и делают для вышвыривания воды из под шины. Там даже есть параметр сколько литров за единицу времени. И величине этой позавидовали бы самые крупные насосы.
Найдя донора но в другом форм факторе, с «трясущимися руками» и надеждой не убить окончательно единственную рабочую машину, я всё же решился на пересадку.
В результате на мат плате нарисовался похожий ёжик, как в статье. И какая же была радость когда работал и LPT — через который я программировал, и заработали оба COM порта. Ностальжи…
И что бы поиграть, мне приходилось писать простенькие игры. Карточные, змейки, стрелялки и прочее… Запускать, играть. После выключения всё удалялось. В следующий раз всё по новой ))))
Во вторых. Например я никогда не оставляю код с предупреждениями. И в 99% случаях они правильные. Но всегда есть нестандартные случаи. Например навскидку:
Компилятор C# всегда ругается на не инициализированные переменные. Но проблема в том что он не смотрит вглубь кода больше чем на 1 уровень. И если инициализация будет после двух if — он этого не увидит.
Опять же у меня в практике был случай когда статические классы инициализировать через рефлексию — тоже была ругань. Ну и так по мелочи.
Опять же если речь про C# — то это живой язык и там чуть лине через день прилетают обновы. И порой прилетает такое — что вполне рабочий код становится жёлтым на половину. А всё потому что решили ввести новое предупреждение — не помню что, что то с null связано было. Пришлось отключать это через настройки глобально.
Например есть человеческая фраза: «Не лезь в розетку — убъёт!»
В программировании будет выглядеть так:
Не лезь в розетку — убъёт!
ЕСЛИ ты электрик — то можешь лезть
ЕСЛИ в розетки есть напряжение 220 и ты электрик — не лезь
ЕСЛИ ты электрик но в перчатках — то лезь
ЕСЛИ напряжении 10kV и ты в перчатках — не лезь
ЕСЛИ напряжении 10kV и ты используешь клетку Фарадея и специальный уравнивающий щуп…
И т.д. миллион вариантов
Что бы не писать миллион букв (привет бейсику )) просто всё заменяется на X,Y,Z и прочие переменные, а условия на операторы if,for и другие.
И вуаля! Получаем язык С. На котором удобно писать программы и понимать их. И не нужны никакие прослойки.
А с радиацией я вообще не понял взаимосвязь. Она разрушает процы путём открытия двух противополярных комплементарных транзисторов которые образуют КЗ. И собственно проц разрушает не сама радиация, а короткое замыкание и в следствии разрушительное выделения тепла. И современные радио-стойкие процы, они радио-стойкие не потому что какие то другие материалы используются, а потому как схема там строится так что бы отлавливать такие КЗ и отключать эти участки, что бы сами себя не поджарили.
Может взаимосвязь в том что новый метериал выдерживает больше температуры (300C)? Но кз нагревает локально участки до тысячи градусов.
Плюс делать не одну простую проверку за цикл, а как минимум 3 — на предмет удаления строки, на предмет новой строки, на предмет изменения данных. И это только что всплыло в обсуждении. Что там ещё при разработке всплывёт?
Это я не упоминаю про индексы. Это те же самые массивы. Для них тоже придётся всякие служебные колонки вводить. И вообще непонятно что будет с раздвоенным индексом, в варианте вставки/удалении строк.
Я не говорю что идея плохая. Просто в представленном виде она имеет критичный оверхед. Но зерно в ней есть, надо подумать над ней, может получится усовершенствовать.
Например как учитывать новые добавленные строки? В старой таблице не будет этих строк и собственно не будет 4-го поля для анализа.
Как учитывать удалённые строки? Это придётся ещё тогда служебный столбец добавлять типа deleted. И его тоже анализировать при каждом цикле?
Одновременно транзакция write может работать только 1. Потому как на каждый write придётся дублировать все эти поля.
И что получаем. На каждый цикл проверки делать дополнительную проверку 4 поля. И того если имеем миллион строк. Проверок делаем 2 миллиона при переборе (в случае когда условие например придётся на последнюю строку). А если учесть что это будут if с переходом — то скорее всего поломается оптимизация в проце для чистого перебора массива.
Далее мы должны в каждой таблице загруженной в RAM делать дополнительную колонку — например int. И того на 1M строк имеем лишние 4Mб данных.
Меня больше всего волнует потеря производительности для двойной проверки каждой строки.
То что вы описали — это то что описал и я. В цикле для каждого столбца каждой строки придётся вызывать функцию которая будут проверять изменялось ли значение. Проверка это будет в общем случае как перебор другого массива в котором будут например структуры (номер строки, номер столбца, новое значение). И избавится от этого дикого оверхеда не получится.
С другой стороны имеем тот же массив массивов + новые изменённые данные. Где их хранить? Ну допустим имеем новый массив. В котором например структуры (номер строки, новое значение). Тогда вместо простого for, мы должны на каждом цикле делать запрос к новому массиву, перебирать его и искать изменённую строку. Получаем дикий оверхед. Как избавится от этого оверхеда? Так на вскидку ничего нормального в голову не приходит. А если изменений на гигабайт — то вообще получим неработоспособную систему — такой SELECT просто зависнет навечно.
И тут получаем мой вопрос — а ради чего это нужно?
Пока напрашивается простой вариант — сделать 2 вида транзакций:
Fast — это в которых нету внутренних select, либо нас устраивают устаревшие данные. В таких транзакциях блокировать таблицу в конце транзакции.
И второй вариант — с полной блокировкой таблицы.
Что касается собственной разработки БД.
По поводу преимуществ собственной разработки уже были да и будут миллион дискуссий, более того всё существующее ПО это когда то собственная разработка. Но я согласен — без явной причины, на такой подвиг я бы не согласился ни за что. Нас вполне устраивал Postgres. Тут мне в личку писали, я там подробно ответил причину почему всё таки своя БД. Приведу ответ тут:
Выигрыш записывать изменения в конце транзакции только в том что это время будет меньше чем время всей транзакции.
В нашей БД такой механизм применить легко даже не сильно меняя код. А именно. При каждом INSERT/UPDATE/DELETE — идёт запись в WAL. Так вот просто комментировать строку изменения таблицы, при этом изменения WAL останется. А в конце транзакции применить WAL к таблицам. Точно также как WAL применяется при старте БД. Также решается мега геморрой отката транзакции — его просто не будет, потому как таблицы RAM не изменились.
Но тогда внутри транзакции SELECT будет работать на устаревших данных.
И ещё непонятно. При старте транзакции указывается список таблиц которые должны быть неизменны на момент старта транзакции, транзакция же атомарна, что бы вся логика внутри транзакции отработала правильно. Но в случае если не блокировать таблицы — и изменения в них могут вносить другие транзакции, может получится каша.
Например делаем внутри транзакции SELECT сколько денег у клиента. Возвращается что 100$. Далее идём делать какую то логику. А в этот момент в другой транзакции снимаем эти 100$. Но при этом мы находимся в первой транзакции и она работает по логике что у клиента есть 100$.
Короче есть на чем подумать. Если внутри транзакции ненужны селект — то можно не блокировать таблицы на время транзакции. В сценариях описанных выше — такой подход неприемлем.
Но по поводу страниц хотел бы сказать зачем мы их применили у себя. Не буду описывать тернисты путь, как мы выбирали размер и прочее, напишу 2 главные причины.
Страницы на диске по 8Кб — основная причина, если мы изменили 1 байт в таблице, не хотелось бы переписывать 16Мб на диске, если страница например 16Мб. Изначально такой размер был выбран для получения преимуществ в скорости чтения с диска, и количества файлов в файловой системе, которое тоже ограничено, и прочего. Но последующая разработка показала оптимальным всё таки размер совпадающий с размером странице диска.
Страница в RAM — тоже равна 8Кб. Основная причина — экономия RAM. Загружать в RAM только те страницы которыми пользуешься.Опять же если страница RAM и DISK одинакового размера — то упрощает их синхронизацию.
И Вакуум запускается для диска. Потому как на диске используется страничная организация памяти.
А вот для RAM — там можно безнаказанно выделять и удалять память. Иначе можно вставить гигабайт данных, а потом удалить. И что этот гигабайт будет висеть мёртвым грузом в RAM?
Но я не знаю как точно работает postgres. Я написал как это должно работать по логике.
Прочитав ваш комментарий я прекрасно удивил одну из проблем которую мы решали в процессе проектирования. И у меня возник вопрос.
Собственно как работает доступ к таблицам. Разные потоки делают запросы на read — при этом таблица лочится — но все могут получить доступ на чтение. Если в очереди запросов подходит запрос write — то ожидается пока все read не закончатся, потом лочится на write — и далее с таблицей работает 1 поток.
Все INSERT/UPDATE/DELETE — это write запросы и делаются внутри транзакции. И представим ситуацию — мы сделали UPDATE на гигабайт данных, или DELETE — а далее делаем SELECT в тойже транзакции — и мы должны получить уже изменённые данные. Самое простое — это когда мы залочили таблицу и делаем изменения прямо в ней. И Select тоже в ней. Если придётся откатывать транзакцию — то это тяжёлая операция. В нашем случае — идёт восстановление таблицы из журнала WAL. Также при откате Текущий WAL транзакции не записывается на диск.
Вы же описали ситуацию когда изменения INSERT/UPDATE/DELETE не делаются в существующие таблицы, а делаются кудато в другое место. Ну допустим в массив какой-то. Соответственно в это время с таблицей могут работать другие в режиме read.
Но как тогда делать SELECT? Путь это простая таблица без индексов. Это будет набор массивов в котором просто циклом перебираем строки. Но в вашем случае надо как то знать какие строки изменённые.
Конечно можно придумать геморройный механизм этого. Но это будет намного медленнее и жрать память. Простой перебор одномерного массива намного быстрее, чем перебор с проверкой — а не изменилась ли строка? А ещё надо учитывать DELETЕ — который может вообще пол таблицы в разных местах выкинуть.
Вобщем вопрос — а нужно ли такое поведение? Я вижу как минимум например засаду в следующем сценарии. Сделали платёж — запустился скрипт изменения баланса в БД — но подавис по времени. Если сделать сразу новый платёж — то мы получим неправильный баланс денег.