> begin; set sum=sum-b where id='c'; set sum=sum+b where id='d'; commit; выполнившегося примерно По логике вещей: старое состояние - то что было до begin. Новое - то что должно стать после commit. Если удалось закрыть commit - все получают что прописано. Если не удалось, все возвращается в вид как было до этого - и должно быть переделано еще раз на других уровнях. В этом вроде бы весь пойнт транзакционной модели - и само по себе это может быть уложено в логику CoW. Другое дело что не факт что general purpose CoW будет сильно оптимален для конкретного кейса в вон той СУБД, но вообще, вывесить семантику CoW юзермоду более явно таки напрашивается, а дальше пусть они сами смотрят, ОК им оно или все-же свой самопал лучше.
> fs при этом консистентна, предположим. Файл читается (то есть внутри не появилась
> пачка нулей просто так, потому что блок распределили а записать его
> не успели - это вот то от чего гарантирует CoW
CoW сам по себе может гарантировать, что либо тот write завершен полностью как задумано, либо откачен целиком как будто его никогда не было. А так что он на середине встрял и в этот момент все фигакнулось - в CoW по логике при нормальной реализации исключено. А в ext4 без полного журнала есть файл где write дошел до середины, все упало - и после краха у ФС нет данных ни чтобы обломаную запись откатить, ни чтобы ее доделать. На то и журнал только метаданных. Оно при этом логически консистентно по описанию файла в метаданных, но содержимое файла некорректное и программы совершенно не обязаны его понять. Удачи декодировать жыпег состоящий из старой и новой половинки. Скорее всего получишь характерный вид: полфоты + инопланетный пейзаж на второй половине, или даже "decode error".
> и не помогает журнал только метаданных).
А при чем тут CoW? Это описание для обычного in-place патчинга.
> Просто вторая операция недовыполнилась и CoW остановилась на полдороге.
Если операций несколько - это уже другой вопрос. А если одна - атомарный подход все же возможен. И вот тут оно не может на полдороги встрять - незавершенная запись будет просто отброшена. И наверное лучше получить либо старый, либо новый жыпег, а не похабное нечто с половиной нового и трэшом от decode error в второй половине.
> fs ничего не знает о "той" или "не той".
Почему, для 1 сискола - знает. А если программа делала 20 сисколов ... эм... чего я там говорил про API для вывешивания CoW семантики? Ну, в общем, логично было бы вывесить им условные "transaction_begin()" и "transaction_commit()" чтобы они не изобретали подобные велики через задний проход с дикими костылями. На CoW это можно нормально сделать.
> fs можно что-то подсказать только сделав fsync - но это медленно.
Это сравнительно медленно, НО гарантирует целостность. А все это + записать 2 раза, в журнал и основную область крупные объемы еще медленнее.
> да. Причем первая запись еще и синхронная, с ожиданием подтверждения.
Абстракция такая.
> И любая обеспечивающая транзакционную целостность субд - так и делает.
Версионирующие и т.п. штуки могут до какой-то степени обойти этот момент используя CoW. Как минимум, им не надо сохранять данные которые они меняют чтобы иметь возможность откатиться.
> восстановления, но вот лог транзакции сохраняется целиком и она не подтвердится
> пока не будет сохранена.
Смотря кто и что понимает под "логом транзакции". Формальное намерение чего хотели сделать - одно. Все перетряхиваемые "блоки" (rows, columns, ...) - совсем другое. У CoW техник их плюс в том что не надо париться насчет старого состояния, оно остается "нахаляву" и на него можно вернуться. А вот если это in place, там уже про халяву речь не пойдет, придется явно писать undo для всего что вообще затронуто. Ну или как это откатывать, just in case?
> А для fs это просто lseek/write/lseek/write - и она не знает, это
> одна транзакция или две разные.
Да я намекал что из CoW можно сравнимую семантику нативно вывесить программам, не для СУБД, а вообще, для файловых операций. Забив на те адовы эрзац костыли с переименовкой и проч.
Ну то-есть, пакетный манагер мог бы как-то так:
transaction_begin();
write(file1);
write(file2);
write(file3);
transaction_commit();
...и при этом у нас либо система с старым пакетом, либо система с новым пакетом, но никогда не система с полураспакованным пакетом. В принципе, снапшотами + хуками пакетника даже можно изобразить такую семантику. Но нативный апи в ос был бы определенно надежнее, быстрее и лучше чем самопальные костыли.
> этот режим работы просто никто не тестирует.
Вполне вероятно. Потому что по состоянию на сейчас это как-то довольно экзотично звучит.
> Поэтому идея sqlite с rename (который почти всегда атомарный) на самом деле
> не так уж ужасно плоха,
Да это не только их идея. Так вроде даже transmission файло пишет. Потому что юзеры заколебали "вай-вай, статус торента профакался при крахе!!!111". Однако сие приводит к куче журнальной логики и костылей в каждой уважающей себя апликухе и странным результатам у тех кому было впадлу столько чудес самим кодить или они просто не парились.
> Гарантированно работает в любой системе вплоть до msdos.
А также гарантирует дофейхоа побочного кода не относящегося в общем то к делу. Это сойдет для СУБД, но когда этим начинает заниматься даже качалка торентов или офисный пакет - это, наверное, уже перебор и по хорошему надо выкинуть скелеты из шкафов пересмотреть семантику операций.