мдя, неужели в эпоху чатгпт такие вопросы еще могут возникать.
в полноценных базах с логом транзакций только запись в лог транзакций считается коммитом. записалось ли файлы данных или нет, не важно. если записались гигабайты в файлы данных но сервер рестартанул, рестарт откатит транзакцию и зачистит файлы. то же самое в обратной ситуации, если в лог коммит записался, а в файлы не успел (данных кеш не сбросился). при рестарте из лога, данные на в файлы данных накатятся.
Здравствуйте, Sharov, Вы писали:
S>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Это зависит от БД и вообще много от чего.
БД может в кластере быть и тогда вопрос насколько надо нод записать чтоб вернуть ок.
WBR, Igor Evgrafov
Re: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Короче, вопрос про пайплайн добавления данных в базу: S>1) Сначала фиксируем факт добавления данных в лог (durability). Как минимум это так при WAL. S>Как без WAL я, кстати, с ходу не скажу. S>2) Далее я должен эти данные валидировать на предмет всяческих ограничений и уникальности (в таблице). S>3) Добавление данных в файл бд (commit), перестройка индексов и соотв. машинерия при необходимости.
S>Кажется, после шага 2 уже можно вернуть в запрос, что ок или не ок. Ждать шаг 3 уже не обязательно, S>тут все можно сделать асинхронно. S>Хоть это все сильно упрощенно, но отдаленно на реальность похоже? Или все не так, и я все перепутал.
Нет.
1. Все валидации делаются до того, как будет принято решение о внесении изменений.
2. Когда решение принято, дальнейшие шаги теоретически зависят от того, как в СУБД реализована crash recovery. В учебниках пишут про Undo Logging, Redo Logging, и Undo/Redo Logging.
На практике все (кроме студенческих поделок) реализуют последний вариант, он же WAL, он же ARIES. Ну, либо совсем ничего не реализуют, и тогда пайплайн может быть устроен более-менее произвольным образом — либо мы сначала выполняем все модификации синхронно, и только потом подтверждаем коммит, либо мы бодренько подтверждаем коммит, не дожидаясь сброса кэшей на диск. Последний вариант особенно популярен у всяких мамкиных инженеров, которые любят кричать "смотрите, мы делаем в тысячу раз больше коммитов в секунду, чем оракл", пока их не ткнут носом в потери после сбоя.
3. Правила WAL требуют выполнения ровно одной гарантии: для любого изменения запись о нём в лог должна доехать до диска раньше, чем само изменение. Теоретически, это можно реализовать при помощи разворота порядка операций — то есть сначала мы добавляем лог-запись, и только потом вносим изменения в "основные" данные. Но нам всё равно нужно следить за тем, чтобы случайно не записать изменения до сброса журнала на диск.
Наивная реализация (зато очень простая — можно вообще не управлять буферами, а просто отобразить файл данных в память) вынуждена обеспечивать это при помощи сброса журнала на каждое изменение.
Это настолько чудовищно неэффективно при мало-мальской нагрузке, что обычно всё же делают более сложную схему с менеджером буферов. Менеджер перед записью грязной страницы на диск делает flush журнала, что позволяет сбрасывать записи журнала "пачками".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, paucity, Вы писали:
P>Если память не изменяет, в любой момент после записи лога, не обязательно дожидаясь записи самих данных на диск, или нет?
После того, как будет выполнен flush log после добавления в журнал записи commit(TID).
Запись "самих данных" на диск тут полностью асинхронна — она может завершиться ещё до этого момента; может даже и не начаться к этому моменту; может быть частично выполнена к этому моменту.
P>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Современные СУБД не делают "коммит в файл данных". Это слишком дорого. Файл данных лениво синхронизуется с памятью более-менее независимо от коммитов транзакций. То есть в каждый момент в "файле данных" на диске находится каша из изменений, которые внесены незавершёнными транзакциями; устаревших копий страниц, изменённых завершенными транзакциями, но ещё не сброшенных на диск, и прочего мусора.
Но при этом в каждый момент у нас есть на руках фрагмент журнала, который позволяет нам гарантированно навести в этом мусоре порядок.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Непонятно. Все-таки в WAL всегда приезжают валидированные данные, а не просто некий факт добавления в бд? А то может S>быть там есть отдельное поле про валидность вставленных данных в целях оптимизации записи и т.п.
В классический WAL приезжают старые + новые данные. Всё. В нём нам не особо нужна информация про валидность данных.
Если речь про обычные (немедленные) ограничения, то их СУБД проверяет непосредственно перед тем, как выполнить изменение.
Например, если у нас стоит сheck(quantity % 2 == 0), то никакая СУЬД не будет складывать update T set quantity=17 where id = 42 в WAL. Сначала будет выполнена проверка check constraint, и если она сфейлится (получится false), то изменение не будет применено. Блокировочник не станет изменять запись в буфере, версионник не станет создавать новую версию строки. Там в зависимости от окружающего такую операцию кода будет получен отказ, а то и вся транзакция будет откачена.
И только если констреинт удовлетворён, в журнал будет добавлена запись UPDATE(tid=17, table=T, tuple = PK(42), quantity_old = 8, quantity_new = 16).
После этого будет изменено содержимое буфера, содержащего копию кусочка файла данных.
Точно так же проверяются ограничения уникальности и внешнего ключа: проверка наличия нарушений выполняется до применения изменения, и ошибочная операция отменяется.
Отложенные ограничения отличаются тем, что нарушения не отменяют запрошенную операцию, а добавляются в журнал нарушений (обычно ведётся в памяти, т.к. ему не нужно переживать сбои).
Тогда да — в журнал попадает запись про изменение, изменение применяется к буферу в памяти, и мы едем дальше.
И только в момент коммита СУБД достаёт журнал нарушений, и начинает их перепроверять. Если хотя бы одно нарушение всё ещё актуально, транзакция отменяется (в зависимости от модели движка мы либо бежим назад по WAL и восстанавливаем испорченные значения, либо просто фиксируем статус нашей транзакции и оставляем тупиковые версии строк/страниц для сборки мусора).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте.
S>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Ответьте им, что вопрос малость идиотский, особенно учитывая наличие транзакций и возможную вложенность транзакций.
Данные в базу добавлены, когда все транзакции в активном соединении с базой завершены успешно. Куда база их записывает — это её, базы, дело. И в логе они будут, и в файле данных они будут.
Re[3]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Что значит любого изменения? Если оно нарушает какое-нибудь ограничение? Или речь все же про валидные изменения?
Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись.
Потому что иначе после сбоя у нас не будет способа восстановить предыдущее значение.
А если вас беспокоят deferred constraints, то они проверяются между получением от пользователя команды commit transaction и внесением в WAL записи commit(TID). Если какие-то из констреинтов окажутся нарушенными, то информация из журнала будет использована для отката этой транзакции.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Базовый вопрос про добавление(вставку) данных в бд.
S>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Кем считается? Клиентом — когда получил ответ от сервера, что транзакция успешно завершена. На сервере — если он упадёт после записи в лог, но до записи в дату, то при перезапуске должно произойти какое-то recovery, с переходом в 1 из согласованных состояний (транзакцию либо дозавершить либо откатить).
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[2]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sinclair, Вы писали:
S>3. Правила WAL требуют выполнения ровно одной гарантии: для любого изменения запись о нём в лог должна доехать до диска раньше, чем само изменение. Теоретически, это можно реализовать при помощи разворота порядка операций — то есть сначала мы добавляем лог-запись, и только потом вносим изменения в "основные" данные. Но нам всё равно нужно следить за тем, чтобы случайно не записать изменения до сброса журнала на диск.
Возращаясь ко второй части вопроса ТС, когда клиент получает подтверждение, что данные/изменения записаны?
Если память не изменяет, в любой момент после записи лога, не обязательно дожидаясь записи самих данных на диск, или нет?
S>Ну типа когда бд вернет,
что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Re[3]: Базовый вопрос про добавление(вставку) данных в бд.
S>>Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись.
Gt_>не верно. в оракле даже не зафиксированная транзакция вполне может менять данные на диске, просто старое значение уедет в undo лог. конкурирующие транзакции из undo читают.
Что именно не верно?
Первое действие это запись в журнал (копии старых данных или новых данных в зависимости от типа журнала).
Только потом изменения в БД.
Re[4]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, paucity, Вы писали:
P>>Если память не изменяет, в любой момент после записи лога, не обязательно дожидаясь записи самих данных на диск, или нет? S>После того, как будет выполнен flush log после добавления в журнал записи commit(TID). S>Запись "самих данных" на диск тут полностью асинхронна — она может завершиться ещё до этого момента; может даже и не начаться к этому моменту; может быть частично выполнена к этому моменту.
P>>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит? S>Современные СУБД не делают "коммит в файл данных". Это слишком дорого. Файл данных лениво синхронизуется с памятью более-менее независимо от коммитов транзакций. То есть в каждый момент в "файле данных" на диске находится каша из изменений, которые внесены незавершёнными транзакциями; устаревших копий страниц, изменённых завершенными транзакциями, но ещё не сброшенных на диск, и прочего мусора. S>Но при этом в каждый момент у нас есть на руках фрагмент журнала, который позволяет нам гарантированно навести в этом мусоре порядок.
Не то чтобы независимо... Всегда есть определенные правила синхронизации. Иначе может возникнуть ситуация что количество коммитов такое большое что "файл данных" становится все менее и менее актуальным. Результатом будет то что восстановление при сбое будет занимать все большее и большее время. Поэтому асинхронность записи в "файл данных" как правило ограничена — или по объему запаздывающих данных или по времени. Если этот лимит превышается, включается принудительная синхронизация, пока мы не достигнем требуемого лимита.
Базовый вопрос про добавление(вставку) данных в бд.
Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд,
когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет,
что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Короче, вопрос про пайплайн добавления данных в базу:
1) Сначала фиксируем факт добавления данных в лог (durability). Как минимум это так при WAL.
Как без WAL я, кстати, с ходу не скажу.
2) Далее я должен эти данные валидировать на предмет всяческих ограничений и уникальности (в таблице).
3) Добавление данных в файл бд (commit), перестройка индексов и соотв. машинерия при необходимости.
Кажется, после шага 2 уже можно вернуть в запрос, что ок или не ок. Ждать шаг 3 уже не обязательно,
тут все можно сделать асинхронно.
Хоть это все сильно упрощенно, но отдаленно на реальность похоже? Или все не так, и я все перепутал.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте.
S>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
S>Короче, вопрос про пайплайн добавления данных в базу: S>1) Сначала фиксируем факт добавления данных в лог (durability). Как минимум это так при WAL. S>Как без WAL я, кстати, с ходу не скажу. S>2) Далее я должен эти данные валидировать на предмет всяческих ограничений и уникальности (в таблице). S>3) Добавление данных в файл бд (commit), перестройка индексов и соотв. машинерия при необходимости.
S>Кажется, после шага 2 уже можно вернуть в запрос, что ок или не ок. Ждать шаг 3 уже не обязательно, S>тут все можно сделать асинхронно. S>Хоть это все сильно упрощенно, но отдаленно на реальность похоже? Или все не так, и я все перепутал.
S>Заранее благодарю.
S>Упд: 1 и 2 прекрасно параллелятся.
Тут ответ зависит от того, что предпримет база при перезапуске в случае сбоя между записью в лог и записью в файл, например при отключении питания. Если посмотрит лог, а потом добавит не записанные записи в файл, то запись в лог = записи в файл, а так помимо просто записи есть еще и транзакции.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте.
S>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит?
Возможно вопрос с подвохом?
По сути, данные добавлены в БД тогда, когда мы их можем получить обратно.
Например, в BASE базах, удачная вставка данных, не гарантирует что мы можем вычитать их сразу же.
- Слава России!
— Героям СВО Слава!
Re[2]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Qulac, Вы писали:
S>>Заранее благодарю. S>>Упд: 1 и 2 прекрасно параллелятся. Q>Тут ответ зависит от того, что предпримет база при перезапуске в случае сбоя между записью в лог и записью в файл, например при отключении питания. Если посмотрит лог, а потом добавит не записанные записи в файл, то запись в лог = записи в файл, а так помимо просто записи есть еще и транзакции.
По классике так. Но тут речь скорее всего идет о том, что вернется клиенту. И возвращать ок клиенту после
добавления в лог как-то странно, а если данные не пройдут валидацию? Кажется, что можно 1 и 2 шаг выполнять
одновременно и по результатам обоих выдавать ответ. Иначе получится, что данные записали в лог, но они
не пройдут валидацию. И что тогда?
Кодом людям нужно помогать!
Re[2]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Osaka, Вы писали:
S>>Тут на собеседовании спросили на тему когда считается, что данные добавлены в бд, S>>когда мы записали их в лог или непосредственно в файл данных? Ну типа когда бд вернет, S>>что данные добавлены, после добавления данных в лог или когда в сам файл данных будет комит? O>Кем считается? Клиентом — когда получил ответ от сервера, что транзакция успешно завершена. На сервере — если он упадёт после записи в лог, но до записи в дату, то при перезапуске должно произойти какое-то recovery, с переходом в 1 из согласованных состояний (транзакцию либо дозавершить либо откатить).
Ответ от сервера когда приходит, очевидно, что не сразу после записи в лог, а если данные не валидны?
Кодом людям нужно помогать!
Re[4]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Qulac, Вы писали:
S>>>Заранее благодарю. S>>>Упд: 1 и 2 прекрасно параллелятся. Q>>Тут ответ зависит от того, что предпримет база при перезапуске в случае сбоя между записью в лог и записью в файл, например при отключении питания. Если посмотрит лог, а потом добавит не записанные записи в файл, то запись в лог = записи в файл, а так помимо просто записи есть еще и транзакции.
S>По классике так. Но тут речь скорее всего идет о том, что вернется клиенту. И возвращать ок клиенту после S>добавления в лог как-то странно, а если данные не пройдут валидацию? Кажется, что можно 1 и 2 шаг выполнять S>одновременно и по результатам обоих выдавать ответ. Иначе получится, что данные записали в лог, но они S>не пройдут валидацию. И что тогда?
Насколько мне известно при запуске после сбоя все действия которые не были зафиксированы транзакциями — отменяются, если эти данные еще были записаны в журнал, то запись в журнал не означает что данные в бд сохранены.
Программа – это мысли спрессованные в код
Re[2]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Gt_, Вы писали:
Gt_>мдя, неужели в эпоху чатгпт такие вопросы еще могут возникать.
Выбирал, или-или. Решил здесь, расчитывая на некую дискуссию. А всяческая нежить может и наглючить.
Gt_>в полноценных базах с логом транзакций только запись в лог транзакций считается коммитом. записалось ли файлы данных или нет, не важно. если записались гигабайты в файлы данных но сервер рестартанул, рестарт откатит транзакцию и зачистит файлы. то же самое в обратной ситуации, если в лог коммит записался, а в файлы не успел (данных кеш не сбросился). при рестарте из лога, данные на в файлы данных накатятся.
Похоже на правду, благодарю.
Кодом людям нужно помогать!
Re[2]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sinclair, Вы писали:
S>3. Правила WAL требуют выполнения ровно одной гарантии: для любого изменения запись о нём в лог должна доехать до диска раньше, чем само изменение. Теоретически, это можно реализовать при помощи разворота порядка операций — то есть сначала мы добавляем лог-запись, и только потом вносим изменения в "основные" данные.
Что значит любого изменения? Если оно нарушает какое-нибудь ограничение? Или речь все же про валидные изменения?
Кодом людям нужно помогать!
Re[4]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, paucity, Вы писали:
S>>1. Все валидации делаются до того, как будет принято решение о внесении изменений.
Ну, это я немножко погорячился. Некоторые СУБД поддерживать deferred constraints. Это позволяет нам решать всякие проблемы типа кольцевых ссылок между таблицами — как нам вставить отдел, если у него обязательный FK на начальника отдела, и как нам вставить начальника отдела, если у него обязательный FK на отдел, в котором тот работает?
Но достигается это ценой ведения отдельного журнала нарушений с перепроверкой этих нарушений при commit. То есть нагрузка на СУБД увеличивается.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Sharov, Вы писали:
S>>Что значит любого изменения? Если оно нарушает какое-нибудь ограничение? Или речь все же про валидные изменения? S>Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись. S>А если вас беспокоят deferred constraints, то они проверяются между получением от пользователя команды commit transaction и внесением в WAL записи commit(TID). Если какие-то из констреинтов окажутся нарушенными, то информация из журнала будет использована для отката этой транзакции.
Непонятно. Все-таки в WAL всегда приезжают валидированные данные, а не просто некий факт добавления в бд? А то может
быть там есть отдельное поле про валидность вставленных данных в целях оптимизации записи и т.п.
Кодом людям нужно помогать!
Re[4]: Базовый вопрос про добавление(вставку) данных в бд.
S>>Что значит любого изменения? Если оно нарушает какое-нибудь ограничение? Или речь все же про валидные изменения? S>Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись.
не верно. в оракле даже не зафиксированная транзакция вполне может менять данные на диске, просто старое значение уедет в undo лог. конкурирующие транзакции из undo читают.
в мсскл версионный режим примерно тоже самое, а блокировочный на сколько я помню тоже вполне себе меняет данные на диске, если транзакция крупней кешей. просто держит эксклюзивную блокировку и фиг кто эти изменения увидит.
если транзакция крупнее ram, не так много вариантов.
Re[6]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, m2user, Вы писали:
S>>>Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись.
Gt_>>не верно. в оракле даже не зафиксированная транзакция вполне может менять данные на диске, просто старое значение уедет в undo лог. конкурирующие транзакции из undo читают.
M>Что именно не верно? M>Первое действие это запись в журнал (копии старых данных или новых данных в зависимости от типа журнала). M>Только потом изменения в БД.
вот это не так " но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись."
Re[7]: Базовый вопрос про добавление(вставку) данных в бд.
S>>>Что значит любого изменения? Если оно нарушает какое-нибудь ограничение? Или речь все же про валидные изменения? S>>Про любые. Если мы вообще собрались вносить в базу изменение, то в RAM можно резвиться как угодно, но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись.
Gt_>не верно. в оракле даже не зафиксированная транзакция вполне может менять данные на диске, просто старое значение уедет в undo лог.
Ваше утверждение никак не противоречит моему.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Gt_, Вы писали:
Gt_>вот это не так " но на диск это изменение не должно попасть до того, как в WAL уедет соответствующая запись."
Совершенно именно так, как я написал.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Базовый вопрос про добавление(вставку) данных в бд.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Enomay, Вы писали:
S>>>Ответ от сервера когда приходит, очевидно, что не сразу после записи в лог, а если данные не валидны? E>>После коммита транзакции.
S>Ага, т.е. после записи в файл бд?
Ну смотря что понимается под "файлом бд".
Как тут уже говорили, запись в "файл бд" чаще делается асинхронной. Если они лежат в страничном кеше и читаются оттуда, и могут быть восставлены из лога при сбое,
то "файл бд" тоже превращается в своего рода кеш (для лога). Если данные вытесняются из страничного кеша, тогда они могут писаться на диск (как кеш второго уровня).
Но это все равно вторично. Что первично — это запись в лог. Это все конечно по разному работает в разные DBMS, в зависимости от того на чем фокусируются / что оптимизируют разработчики.
И тем более по разному в разных типах БД — в аналитических оптимизируют совсем другое, в embedded тоже, а в in-memory вообще нет "файла бд" .