SQLite и разветвление безопасно - PullRequest
0 голосов
/ 09 июня 2018

У меня есть приложение, в котором много читателей базы данных SQLite работают параллельно, каждый в своем собственном процессе.Процессы могут разветвляться ... и могут делать это после установления соединения SQLite.

Я хотел бы написать обработчик разветвления, чтобы при разветвлении родительского процесса все состояние SQLite«обновляется» в дочернем процессе ... это означает, что все подготовленные операторы, соединения с базой данных и другие ресурсы немедленно удаляются без очистки.

Как библиотека, SQLite управляет своей собственной памятью и другими ресурсами, так что теоретическивозможно.

По сути, я хочу дублировать состояние приложения, отличного от SQLite, при разветвлении, но иметь состояние SQLite, которое будет присутствовать, если программа начнет выполняться через exec*, а не fork.

Если возможно, то, что я хочу сделать, было бы примерно так:

void sqlite_refresh(void)
{
     // discard all sqlite-specific state
     // make all sqlite3_db, sqlite3_stmt &c pointers NULL
     return;
}

// call this code somewhere
pthread_atfork(
     /* prepare */ NULL,
     /* parent */  NULL,
     /* child */   sqlite_refresh
);

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

SQLite выдает следующее зловещее предупреждение в своей документации об использовании fork:

Не открывайте соединение с базой данных SQLite, затем fork (), затем попытайтесь использовать это соединение с базой данныхв дочернем процессе.В результате возникнут все виды проблем с блокировкой, и вы легко можете получить поврежденную базу данных.SQLite не предназначен для поддержки такого поведения.Любое соединение с базой данных, которое используется в дочернем процессе, должно быть открыто в дочернем процессе, а не наследоваться от родительского процесса.

Даже не вызывать sqlite3_close () для соединения с базой данных из дочернего процесса, если соединение было открытов родительском.Можно безопасно закрыть базовый дескриптор файла, но интерфейс sqlite3_close () может вызвать действия по очистке, которые удалят содержимое из-под родительского, что приведет к ошибкам и, возможно, даже повреждению базы данных.

В нем говорится здесь that

В Unix вам не следует переносить открытую базу данных SQLite через системный вызов fork () в дочерний процесс.

1 Ответ

0 голосов
/ 09 июня 2018

Дочерний процесс не должен делать что-либо с объектами соединения / оператора, которые он получил от родителя.Это означает, что ваша функция sqlite_refresh() должна быть пустой или что она просто устанавливает все указатели в NULL.(Это подразумевает утечку памяти.)

Лучше было бы не открывать соединение при разветвлении.

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