Здравствуйте, cheese, Вы писали:
C>Вы рассматриваете частный случай, когда изменение затрагивает только запись в таблице, когда объект записи = single B-Tree leaf page. Как насчет обеспечения recovery после сбоя, когда сервер фиксировал на диск изменения в "потрохах" B-Tree, т.е. после page split / page merge, если одна страница записалась на диск, а другая — нет?
Здесь работа с индексами ничем не отличается от работы с данными. Измененная версия, до фиксации транзакции ее изменившей, не считается актуальной. Так что тут вроде бы все чисто.
C>Вообще, насколько я понимаю (я не профессионал в database internals, так что да поправят меня знающие люди), любая операция, которая переводит образ базы на диске из одного (согласованного) состояния в другое и при этом не атомарна с точки зрения disk I/O (пишет более одного disk I/O unit) — должна быть сначала продублирована где-нибудь в другом месте (в журнале), иначе восстановление после сбоя в общем случае невозможно.
Ну в общем случае все так. И здесь по большому счету тоже самое. Просто фиксация транзакции, одно атомарное действие, начиная с которого все предыдущие изменения, сделанные этой транзакцией, считаются актуальными...
Здравствуйте, dimitr, Вы писали:
D>Только теоретически.
Не, это как раз суровая практика..
D>Одна транзакция для батча может, например, использоваться для уменьшения нагрузки на сервер. И между прочем, SQL-стандарт (и ведущие производители СУБД) поддерживают т.н. точки сохранения (savepoints), которые предназначены для частичного отката изменений в случае локальной ошибки и последующего продолжения транзакции. Это все же не от дурной башки придумали, наверное?
Ну ладно, даже если опустить целесообразность сэйвпоинтов и запуск одним батчем, все равно завязываться не клиента в процессе выполнения нет никакого смысла.
Ведь в 99.9% случаев уже на этапе подготовки транзакции известно, в каком месте ошибка должна приводить к откату, а в каком нет. И вообще как с этой транзакцией поступать в случае сбоя. Для этого вовсе не надо дергать клиента в момент конфликта, никакой дополнительной информации от сервера он не получит.
D>Не обязательно. Моя транзакция может работать в режиме изоляции "read-committed" и, получив отлуп и перечитав изменения, уже _закоммиченные_ моим конкурентом, принять решение о повторной записи.
Ну правильно. Это и есть откат и новый старт транзакции по новой версии данных.
Здравствуйте, dimitr, Вы писали:
D>И что тут плохого?
Зависимость от клиента...
D>Это просто альтернативная реализация, которая имеет свои достоинства и недостатки.
Вот именно эта реализация, в этом месте как раз имеет явный недостаток.
В 99.9% случаев известно еще на этапе подготовки транзакции, что с ней делать в случае сбоя. И дергать клиента нет никакого смысла.
D>Сервер обнаруживает обрыв соединения и откатывает все транзакции скоропостижно скончавшегося клиента.
Ну обрыв-то обнаруживается не сразу...
D>Не поделишься линком на эту тему? Если честно, я плохо представляю, как Оракл это может сделать.
Ну все есть в доке, на oracle.com. Потом есть двухтомный талмуд Тома Кайта, где все это очень хорошо расписано. И, в конце концов, мекка всех ораклоидов сайт вышеупомянутого Тома: http://asktom.oracle.com
C>Вообще, насколько я понимаю (я не профессионал в database internals, так что да поправят меня знающие люди), любая операция, которая переводит образ базы на диске из одного (согласованного) состояния в другое и при этом не атомарна с точки зрения disk I/O (пишет более одного disk I/O unit) — должна быть сначала продублирована где-нибудь в другом месте (в журнале), иначе восстановление после сбоя в общем случае невозможно.
Ну вот в IB так сделано, что подтверждение транзакции — это ИЗМЕНЕНИЕ ОДНОГО БИТА в файле БД. Достаточно атомарно? Получилось изменить бит — транзакция подтверждена раз и навсегда. Не получилось — не подтверждена. Больше ничего не надо. Даже если в ней были тыщи вставленных/измененных/удаленных записей.
Здравствуйте, Merle, Вы писали:
D>> И что тут плохого? M> M> Зависимость от клиента...
Сервер не должен заниматься самодеятельностью.
D>> Это просто альтернативная реализация, которая D>> имеет свои достоинства и недостатки. M> M> Вот именно эта реализация, в этом месте как раз M> имеет явный недостаток. M> В 99.9% случаев известно еще на этапе подготовки M> транзакции, что с ней делать в случае сбоя. И M> дергать клиента нет никакого смысла.
Только что проверил на Оракле. В случае любой ошибки (включая lock conflict) он ведет себя один в один с IB. Т.е. ошибка уходит к клиенту, а транзакция остается активной. И если предыдущие операторы транзакции отработали успешно, то только от клиента зависит, будет ли транзакция отменена полностью или подтверждена частично. И такое поведение полностью подтверждает мое понимание вещей. Единственный [мне известный] случай, когда Оракл (как и IB) откатывает транзакцию сам — это потеря соединения с клиентом.
Здравствуйте, dimitr, Вы писали:
M>> Зависимость от клиента... D>Сервер не должен заниматься самодеятельностью.
Это не самодеятельность, а прямая обязанность.
M>> Вот именно эта реализация, в этом месте как раз M>> имеет явный недостаток. M>> В 99.9% случаев известно еще на этапе подготовки M>> транзакции, что с ней делать в случае сбоя. И M>> дергать клиента нет никакого смысла.
D>Только что проверил на Оракле. В случае любой ошибки (включая lock conflict) он ведет себя один в один с IB. Т.е. ошибка уходит к клиенту, а транзакция остается активной. И если предыдущие операторы транзакции отработали успешно, то только от клиента зависит, будет ли транзакция отменена полностью или подтверждена частично.
Ты чего-то путаешь.
Если отправить на сервер вот такой батч:
begin trans
.....
commit trans
и внутри транзакции произойдет конфликт, то спрашивать клиента, оставляя подвешенной транзакцию, никто не будет.
Произойдет либо откат и старт новой транзакции, если клиент заранее попросил об этом, либо, по умолчанию, откат и сообщение об ошибке.
Транзакция активной не остается. Остается активным только подключение.
Естественно можно на клиенте инициировать транзакцию, а потом поочереди слать команды, тогда конечно все произойдет так, как ты описал.
Но обычно, в здравом уме так не делают... Хотя Оракл, хвастался, мол "теперь вы можете себе это позволить".
Понимаешь, даже обрыв не обязателен. Клиент может поменять пару записей и пойти пиво пить, а коннект при этом будет вполне себе поддерживаться... По таймауту его отрубать?
D>И такое поведение полностью подтверждает мое понимание вещей. Единственный [мне известный] случай, когда Оракл (как и IB) откатывает транзакцию сам — это потеря соединения с клиентом.
В IB, как я понимаю, нет явной возможности управлять транзакциями на сервере.
Иначе подобное решение с ожиданием решения клиента, что делать с транзакцией — очевидная архитектурная промашка.
M>Понимаешь, даже обрыв не обязателен. Клиент может поменять пару записей и пойти пиво пить, а коннект при этом будет вполне себе поддерживаться... По таймауту его отрубать?
Это уже вопрос архитектуры клиентского приложения. Оптимистическая/пессимистическая блокировка... Короткие/длинные транзакции... и т.п.
Здравствуйте, Merle, Вы писали:
M> Ты чего-то путаешь.
Да ну? ))
M> Если отправить на сервер вот такой батч: M>
M> begin trans
M> .....
M> commit trans
M>
M> и внутри транзакции произойдет конфликт, то спрашивать клиента, M> оставляя подвешенной транзакцию, никто не будет.
А тут клиент-то почти и не причем, получается.
M> Произойдет либо откат и старт новой транзакции, если клиент M> заранее попросил об этом, либо, по умолчанию, откат и M> сообщение об ошибке. M> Транзакция активной не остается. Остается активным только M> подключение.
Увы, я такими батчами мыслить не умею
M> Естественно можно на клиенте инициировать транзакцию, а потом M> поочереди слать команды, тогда конечно все произойдет так, M> как ты описал.
Именно об этом я и говорил.
M> Но обычно, в здравом уме так не делают... Хотя Оракл, хвастался, M> мол "теперь вы можете себе это позволить".
Давай не будем о здравом уме Ты пытаешся критиковать IB с точки зрения Оракла, который может запускать транзакции на стороне сервера. Я тебе отвечаю с точки зрения IB, который этого делать не умеет. Мы просто не можем прийти к консенсусу, по определению, ибо работаем с базой по-разному. То, что для тебя дикость — для меня единственный и вполне логичный подход к SQL-программированию, и наоборот.
M> Понимаешь, даже обрыв не обязателен. Клиент может поменять пару M> записей и пойти пиво пить, а коннект при этом будет вполне себе M> поддерживаться... По таймауту его отрубать?
Нет, конечно. Я просто хотел показать, что при управлении транзакциями с клиента оба сервера ведут себя абсолютно идентично. Что есть правильно. Поэтому никаких претензий к IB тут быть не может
M> В IB, как я понимаю, нет явной возможности управлять транзакциями M> на сервере.
Здравствуйте, dimitr, Вы писали:
D>А тут клиент-то почти и не причем, получается.
Так и должно быть...
M>> Естественно можно на клиенте инициировать транзакцию, а потом M>> поочереди слать команды, тогда конечно все произойдет так, M>> как ты описал.
D>Именно об этом я и говорил.
Ну понятно, IB по другому не умеет...
D>Давай не будем о здравом уме Ты пытаешся критиковать IB с точки зрения Оракла, который может запускать транзакции на стороне сервера.
Не, я пытаюсь критиковать IB с точки зрения зависимости от клиента.
D>То, что для тебя дикость — для меня единственный и вполне логичный подход к SQL-программированию, и наоборот.
Дык в том-то и дело, что подход не логичный.. Почему — понятно, единственный способ отрубить клиента отошедшего кофе попить — выход по таймауту, что не гарантирует отрубания клиентов, которые действительно делом заняты.
В данном случае, то, что IB чего-то неумеет — это недостаток, а не альтернативный подход...
Я, честно говоря, знал об этой особенности, но у меня вылетело напроч, именно поэтому я все никак не мог понять, что же IB клиента-то спрашивает постоянно...
D>Нет, конечно. Я просто хотел показать, что при управлении транзакциями с клиента оба сервера ведут себя абсолютно идентично.
Дык и MSSQL, при управлении транзакциями от клиента, точно так же себя ведет. По другому-то никак не получится.
D>Что есть правильно. Поэтому никаких претензий к IB тут быть не может
Может... Потому как неправильно это. Преимуществ у такого способа нет, а недостатков — масса, если уж рассуждать об этом, как об альтернативном подходе.
Здравствуйте, Merle, Вы писали:
КДВ>> как завершать транзакции, commit или rollback, в IB решает ТОЛЬКО клиентская часть. M>Ой. Вот явно чуствуется многоверсионность, сколько людей, столько и объяснений... M>А что есть здесь клиентская чать?
клиентская часть — это то, что коннектится к БД, пуляет запросы на сервер, и т.п. Грубо говоря —
gds32.dll (IB API).
КДВ>>И даже это не является причиной для того чтобы сервер пугался и кого-то там откатывал. M>О кей, давайте разберемся с самого начала. M>Допустим последовательная история транзакций приводит к конфликту. T1 пытается обновить запись, которую уже обновила T2, но при этом T2 еще не успела зафиксироваться. M>Далее возможное поведение T1: M>1. Ожидание на блокировке.
если T1 стартовала в режиме WAIT. Если нет (no wait) — T1 просто получит сообщение о том, что запись
обновлена другой транзакцией.
M>2. Откат T1 и новый старт.
нет. T1 сама будет решать — делать commit или rollback. В зависимости от уровня изолированности клиентская
часть программно может или подождать завершения T2 и сделать update снова, либо вызвать rollback.
M>3. Порождение новой версии данных с которой и работает T1, все разборки произойдут при commit'е (first wins, по классике, кто первый встал, того и тапки, кто не успел, того откатывают)
сразу видно человека, который поленился прочитать про многоверсионность
Не-committed версия записи может существовать ТОЛЬКО ОДНА. Т.е. T1 НЕ МОЖЕТ создать новую версию, пока
T2 не сделает commit или rollback. Всего то.
M>Кто принимает решение о дальнейшем развитии событий? Клиент? Не, не может быть..
А почему нет-то? Где тут ситуация, когда серверу надо самому рулить, объясни пожалуйста?
M>В случае любых сбоев, если конечно эт сбои не привели к физической порче диска. M>Тоесть любой сбой, во время любой операции должен быть обратимым и база должна сама прийти в согласованное состояние на момент непосредственно перед сбоем. (требование Durability из ACID так же не должно нарушаться. Что зафиксировано — не вырубишь топором)
Здравствуйте, Merle, Вы писали:
M>Здравствуйте, Romkin, Вы писали:
R>>Брр... Многое зависит от параметров транзакции. В любм случае при фиксации Т2 на клиентскую часть, породившую Т1 пойдет сообщение о deadlock, что решит клиент — его дело. M>А дедлок-то тут причем? Тем дальше в лес, тем толще партизаны. M>Насколько я понимаю, возможно наличие только одной незафиксированной версии данных. Из твоих слов можно заключить, что даже если T1 ждет на блокировке, и таки дожидается, когда T2 зафиксируется, то T1 все равно откатят?
не откатят, а T1 получит сообщение о невозможности сделать update (exception).
Т.е. тут ты все правильно понял. В IB существует в общем случае только один конфликт — попытка
update/delete одной записи двумя конкурирующими транзакциями. Независимо от режима wait
или nowait, такая ситуация называется "deadlock". Не совсем прозрачно, но так получилось.
По крайней мере в каждой ситуации к слову "deadlock" добавляется пояснение с описанием ситуации.
"update conflict on nowait transaction", и т.п.
M>Тоесть дожидаться имеет смысл только в надежде на то, что T2 обломается по своим причинам?
R>>Может-может M>Не, клиент тут ничего не может, а вот TM определяет, что транзакции конфликтны и поступает в соответствии с рекомендациями клиента.
Это вопрос взглядов. IB придерживается схемы, когда именно приложение (!) определяет какие
именно операторы входят в транзакцию. Т.е. только клиент может стартовать транзакцию, и только
клиент может завершить ее тем или иным способом, независимо от тех конфликтов, которые произошли на сервере.
Это потому, что в IB целостность данных проверяется на ходу, именно при выполнении insert/update/delete,
а не отложенно, при commit, как например в MS SQL.
Т.е. в IB commit можно сказать что ничего не делает, просто переводит состояние (!) транзакции из active
в commit и все. а видимость-невидимость версий записей определяется по состоянию транзакций, которые эти
версии создавали.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Romkin, Вы писали: R>>Что значит "повисает"? Транзакция остается транзакцией — клиент ее открыл, вкатывает данные, в конце либо commit либо rollback. Если считать, что транзакция от старта до окончания повисает, тогда да, висит S>Как-то странно это. Ну вот открыл я транзакцию. Работаю-работаю. С клиента. Возникает у меня этот дедлок. И что, я после этого могу продолжать работу? Или сделать commit?
ага. или rollback — как его высочеству ПРИЛОЖЕНИЮ будет угодно.
S>Просто в рамках MS SQL к моменту deadlock кто-то просто должен сделать rollback.
Да просто потому, что у MS SQL изменения в транзакции применяются в момент COMMIT!
А у IB — в момент выполнения этих самых insert/update/delete. Вот и вся разница.
Поэтому MS SQL НЕ МОЖЕТ ничего другого сделать кроме как автоматизированно
выполнить rollback. А в IB — клиент сам может решить, что ему делать.
Здравствуйте, Merle, Вы писали:
M>Здравствуйте, dimitr, Вы писали:
M>Ведь в 99.9% случаев уже на этапе подготовки транзакции известно, в каком месте ошибка должна приводить к откату, а в каком нет. И вообще как с этой транзакцией поступать в случае сбоя. Для этого вовсе не надо дергать клиента в момент конфликта, никакой дополнительной информации от сервера он не получит.
не надо перекладывать идеологию конкретной реализации MS SQL на другие сервера. Не надо.
Ты еще скажи, что в одном коннекте нельзя стартовать несколько транзакций одновременно.
MS SQL этого не умеет? Ну и пусть. IB умеет. Это не плюс и не минус, просто другая
схема обработки транзакций.
D>>Не обязательно. Моя транзакция может работать в режиме изоляции "read-committed" и, получив отлуп и перечитав изменения, уже _закоммиченные_ моим конкурентом, принять решение о повторной записи. M>Ну правильно. Это и есть откат и новый старт транзакции по новой версии данных.
Чего-чего? Какой откат? read committed пока не кончилась живет без "рестартов". И видит чужие
committed изменения.
КДВ>нет. T1 сама будет решать — делать commit или rollback.
Тоесть клиент?
M>>3. Порождение новой версии данных с которой и работает T1, все разборки произойдут при commit'е (first wins, по классике, кто первый встал, того и тапки, кто не успел, того откатывают)
КДВ>сразу видно человека, который поленился прочитать про многоверсионность
Не, если уж мы боремся за чистоту формулировок, то видно человека, который поленился почитать про многоверсионность в IB
КДВ>Не-committed версия записи может существовать ТОЛЬКО ОДНА. Т.е. T1 НЕ МОЖЕТ создать новую версию, пока T2 не сделает commit или rollback. Всего то.
Только в IB.
В формальной теории нет таких ограничений, почитать можно например тут: Concurrency Control and Recovery in Database Systems By
Philip A. Bernstein, Vassos Hadzilacos, Nathan Goodman
КДВ>А почему нет-то? Где тут ситуация, когда серверу надо самому рулить, объясни пожалуйста?
Ну просто непонятнго было зачем клиента дергать в случае ошибки, если всю информацию, о том, что делать с транзакцией после сбоя, можно было отослать вместе с самой транзакцией ище до ее старта.
Но похоже в IB просто нет такой возможности..
Здравствуйте, Merle, Вы писали:
M>Здравствуйте, dimitr, Вы писали:
D>>Не угадал. Инициация исключения и доставка оного на клиентскую сторону. И все. После чего транзакция может быть подтверждена частично или произведен откат. M>Вот здесь вот явная зависимость от клиента... А если в момент доставки эксепшена клиент отвалился, то по такой схеме все становится очень грустно. Транзакция повисает, в нее упираютя другие транзакции, которым нужны данные уже захваченные ей, и так далее..
чего??? опять игнорируем всю информацию, которую дали раньше. в IB нет блокировок, ВООБЩЕ.
Если в момент exception клиент отвалился то это означает:
1. действия, которые привели к exception, НЕ ПРОШЛИ. просто никуда не записались
2. "зависший" клиент будет обнаружен, и сервер автоматически переведет состояние
его транзакций в rollback
3. все, кто будет читать/модифицировать версии, созданные "отвалившимися" транзакциями,
уберут эти изменения как мусор.
Все.
D>>Или ты предлагаешь при конфликте делать рестарт транзакции и накат всех изменений, предшествующих конфликту? Интересно узнать, какая СУБД так поступает... M>Oracle Со многими оговорками и нюансами, понятное дело, но да, примерно так. Да и вообще, классический версионник, по теории, примерно так и должен поступать. И это достаточно логично и оправдано.
Oracle не классический версионник. Версионность в нем введена частично.
M>>> Кто принимает решение о дальнейшем развитии событий? Клиент? Не, не может быть.. D>>Еще как может M>Ну вот не верится мне, что это удачная идея....
Здравствуйте, Merle, Вы писали:
M>Естественно можно на клиенте инициировать транзакцию, а потом поочереди слать команды, тогда конечно все произойдет так, как ты описал. M>Но обычно, в здравом уме так не делают... Хотя Оракл, хвастался, мол "теперь вы можете себе это позволить".
В здравом уме при интерактивной работе клиента с данными никто не отправляет на сервер никаких пакетов.
Ты опять игнорируешь все что тебе пишут. IB сам не стартует и не завершает транзакций на сервере. Просто
не умеет. инициирует работу с транзакциями только клиент.
M>Понимаешь, даже обрыв не обязателен. Клиент может поменять пару записей и пойти пиво пить, а коннект при этом будет вполне себе поддерживаться... По таймауту его отрубать?
это проблемы клиентских приложений и длинных транзакций.
D>>И такое поведение полностью подтверждает мое понимание вещей. Единственный [мне известный] случай, когда Оракл (как и IB) откатывает транзакцию сам — это потеря соединения с клиентом. M>В IB, как я понимаю, нет явной возможности управлять транзакциями на сервере.
наконец-то догадался.
M>Иначе подобное решение с ожиданием решения клиента, что делать с транзакцией — очевидная архитектурная промашка.
Здравствуйте, Кузьменко Д.В., Вы писали:
КДВ>Это вопрос взглядов. IB придерживается схемы, когда именно приложение (!) определяет какие КДВ>именно операторы входят в транзакцию.
Это везде так, вопрос на каком этапе это происходит. IB — приходится дергать клиента, а другие сервера умеют и так и так.
И по вполне очевидным причинам даже для версионника это засада, хотя и меньшая чем для блокировочника.
КДВ>Это потому, что в IB целостность данных проверяется на ходу, именно при выполнении insert/update/delete, КДВ>а не отложенно, при commit, как например в MS SQL.
Не поверишь, целостность данных здесь вообще не причем. и MSSQL и большинство других серверов тоже проверяют ее на каждый оператор.
Отложенная проверка (Differed Referential integrity — DRI) Возможна в Oracle и в Informix, на сколько мне известно, но опять же опционально.
Здравствуйте, Кузьменко Д.В., Вы писали:
M>>Естественно можно на клиенте инициировать транзакцию, а потом поочереди слать команды, тогда конечно все произойдет так, как ты описал. M>>Но обычно, в здравом уме так не делают... Хотя Оракл, хвастался, мол "теперь вы можете себе это позволить".
КДВ>В здравом уме при интерактивной работе клиента с данными никто не отправляет на сервер никаких пакетов.
Ага, по байтно шлют..
КДВ>Ты опять игнорируешь все что тебе пишут.
Нет, просто ты не внимательно читаешь... Я здесь писал про другие сервера, а не про IB.
КДВ>IB сам не стартует и не завершает транзакций на сервере. Просто
не умеет. инициирует работу с транзакциями только клиент.
Оф корс. Вот это-то мне и не нравится.
КДВ>это проблемы клиентских приложений и длинных транзакций.
А транзакции на сервере избавляют клиента от этой головной боли раз и на всегда.
Здравствуйте, Кузьменко Д.В., Вы писали:
КДВ>чего??? опять игнорируем всю информацию, которую дали раньше. в IB нет блокировок, ВООБЩЕ.
Хорошо, переформулирую, нет возможности обновить данные уже обновленные другой транзакцией, если эта другая транзакция не зафиксирована.
Возможно я несколько не понятно излагаю, грешен...
КДВ>1. действия, которые привели к exception, НЕ ПРОШЛИ. просто никуда не записались КДВ>2. "зависший" клиент будет обнаружен, и сервер автоматически переведет состояние КДВ>его транзакций в rollback
И сколько времени пройдет, пока это обнаружится? Это секунды, а секунды — это очень много.
КДВ>Это просто другая идеология.
Обладающая очевидным недостатком..
Здравствуйте, Merle, Вы писали:
КДВ>>1. действия, которые привели к exception, НЕ ПРОШЛИ. просто никуда не записались КДВ>>2. "зависший" клиент будет обнаружен, и сервер автоматически переведет состояние КДВ>>его транзакций в rollback M>И сколько времени пройдет, пока это обнаружится? Это секунды, а секунды — это очень много.
КДВ>>Это просто другая идеология. M>Обладающая очевидным недостатком..
Возможно. Но, кажется, на Linux отваливание клиента обнаруживается системой практически сразу, да вроде и на win это сделано. Не пробовал, правда.
Дело в том, что как правило обновления не особо-то и пересекаются, в отличие от чтений. Да и программировать рекомендуется короткие транзакции, а не держать их как можно дольше.
Простая система — на сервере нет управления транзакциями.