Re[84]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 02.10.21 08:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

НС>>Поэтому кеширование для таких файлов отключается.

S>Нет. Так никто не делает.

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

S>>>В MMF мы не можем этого гарантировать.


НС>>Так не надо лог в MMF писать, о чем и речь.

S>Это как раз понятно. Лог пишется в режиме stream: добавляем всегда в конец. Но отсутствие кэширования (== flush на каждый write) гарантированно убъёт производительность при модификациях.
S>Представьте себе выполнение операции update employee set salary = salary * 1.05 where region = @region.
S>То, что вы предлагаете, означает выполнение flush лога N раз для N записей, попавших под предикат.
S>Это — очень плохое решение, т.к.
S>- на HDD мы получим ограничение быстродействия в ~100 изменений в секунду, т.е. транзакция, трогающая всего лишь 1000 записей, будет выполняться не меньше 10 секунд.
S>- на SSD мы получим многократные перезаписи одной и той же страницы, очень быстро изнашивая диск.

Хм. Это какая СУБД так делает? Я скорее предположил бы что-то типа такого (уточнить по уровню изоляции):
1. Последовательно, или ускоренно по индексу, читаем все записи, ставя лок на запись на каждую подпадающую под условие. Тут можно разгонять упреждающее чтение для скорости.
2. Записываем в WAL изменённые строки для каждой подпавшей под условие; это можно сгруппировать. Ждём подтверждения записи.
3. По команде commit — запускаем (лучше одновременно) запись изменённых версий строк во все соответствующие блоки. СУБД должна сгруппировать эти действия по своим блокам, а диск — обеспечить соответствующее упорядочение и группировку по своим блокам. Ждём завершения всех записей. Одновременность подачи позволяет диску максимально оптимизировать операции.
4. В WAL фиксируем завершение транзакции (ждём подтверждения записи и тогда отдаём ok на commit).

Что тут не так и что может давать какие-то ограничения?

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


Какой именно страницы и в какой это СУБД такое происходит?
Имеется в виду секция WAL? Почему СУБД не может сгруппировать пачку записей для WAL в пределах одной транзакции?

НС>>Так что тут если какое то буферизирование при записи в лог и делать, то только чисто программное, на уровне прикладного кода.

S>По большому счёту, нам всё равно, как устроена буферизация при записи в лог. Там главное — возможность сделать честный flush() в нужный приложению момент.

flush() в таком виде нужен только для оптимизации синхронных операций записи. Асинхронным он даже вреден (точнее, вредно кэширование, которым он управляет — поэтому для асинхронных операций он бессмысленен).
Но пусть вы даже работаете синхронными операциями. При необходимости обеспечить строгую последовательность действий: запись операции в WAL — модификация таблиц — завершение транзакции записью в WAL, что запись состоялась, значит, что должен быть логический барьер
1) все записи действий в WAL идут до всех записей в таблицу;
2) все записи в таблицу идут до финализации в WAL,

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

S>2. Открыть файл c флагами FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH. Тогда можно делать просто FileStream.Flush().

S>Подчеркну: в обоих случаях мы делаем Flush лога на на каждое изменение, а только на каждый commit transaction. То есть транзакция, которая трогает 1000 записей, будет выполняться ~10ms (если выбранный размер буфера достаточен для того, чтобы избежать промежуточных сбросов в процессе исполнения).

НС>>И, в любом случае, MMF для файла лога бессмысленен и бесполезен, там все равно запись и чтение строго последовательные.

S>Речь идёт про MMF для файла данных.

Неудобно, потому что нельзя инициировать независимо пачку операций на одну транзакцию. Разве что одна окажется одним связным куском, тогда может быть msync() (или что там в Windows) на кусок и ядро будет параллелить операции (если может).
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.