последовательная запись многих блоков с O_DIRECT - PullRequest
1 голос
/ 04 февраля 2012

Я работаю над ядром базы данных для Linux, и у меня есть вопрос о согласованности в отношении записи множества блоков одним системным вызовом в ядро.Я открываю устройство с помощью O_DIRECT.

Устройство записывает данные в блоках, в зависимости от аппаратного обеспечения это может быть 512, 2048 или 4096. Допустим, я буду записывать 2 блока по 512 байт за один системный вызов.Что произойдет, если система выключится ровно после того, как диск записал 1 блок?Во время нормальной работы системный вызов write () будет возвращать размер записанных данных, поэтому я мог бы сравнить и сгенерировать ошибку, когда 2 значения (по сравнению с возвращенными) не совпадают, но при отключении питания это усложняется.Это еще сложнее, поскольку ядро ​​может отправлять запросы на запись на устройство не в том порядке, в котором вы его указали, поэтому хвост запроса может быть записан перед заголовком, и тогда у вас будет отключено питание.

Учтите, что ядро ​​базы данных записывает журнал транзакций.Допустим, транзакция составляет около 4096 байт, движку потребуется записать 8 блоков по 512 байт.Внезапно у нас отключение питания, и только половина запроса была написана.Как базы данных справляются с этими проблемами?Я полагаю, чтобы обойти это, вам сначала нужно записать количество блоков, которые вы собираетесь записать, в другое место на диске.Как только вы получили правильное возвращаемое значение, вы можете записать свои данные.Затем, после получения подтверждения, вы должны отправить еще одну запись на диск, обновив информацию о том, что все блоки, которые вы хотели записать, были успешно записаны.Таким образом, для этого потребуется 3 операции записи, и если ядро ​​выполняет запись на диск из других процессов, это, скорее всего, приведет к 3 поискам.Слишком неэффективно.

Я ищу способ добиться согласованной записи множества блоков с помощью только одной операции записи на диск.(одна запись () syscall) Возможно ли это?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2012

Вам необходимо сначала выключить ядро ​​базы данных, а затем выключить систему! .. Когда вы выключаете движок, он должен сначала завершить все записи, синхронизировать (очистить буферы) и привести двигатель к нормальной остановке. Вы также можете включить команду в свой скрипт выключения системы, чтобы сначала выключить двигатель, прежде чем выключать систему.

0 голосов
/ 04 февраля 2012

По модулю некоторых скоростных хаков, описанное вами поведение двойной записи - это именно то, что делают базы данных.Это называется запись с опережением записи и включает в себя один буфер, который записывается в последовательном порядке с помощью операций, и периодическую очистку буферов памяти на диск с соответствующей записью сброса, записанной в журнал.Затем, когда система базы данных начинает работать, она проверяет в журнале записи, которые, возможно, не были записаны на диск, и сбрасывает эти значения на диск (поскольку записи находятся в журнале).

Это может быть на самом делеболее производительным, чем запись данных сразу.Журнал является последовательным файлом, поэтому добавление данных в него не требует поиска, только задержка вращения.Кроме того, вам не нужно сразу записывать данные в фактические файлы данных, поскольку вы всегда можете восстановить их из журнала.Затем, когда не поступает никаких запросов, вы сбрасываете данные на диск и записываете запись в журнал.Таким образом, единственное время, которое ищет СУБД: 1) когда система в остальном работает тихо и 2) когда в DMBS заканчивается память для хранения измененных данных.Пока у вас достаточно памяти на вашем компьютере, поиск на диске почти не выполняется, и эти поиски происходят, когда СУБД все равно не занята.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...