У меня есть приложение, в котором много читателей базы данных 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 () в дочерний процесс.