#Что происходит и когда инструкция применима
SQLite может показывать «старые» данные при параллельной работе из-за продолжающейся транзакции чтения: в WAL читатель видит согласованный снимок до начала новой транзакции. Нужно завершить чтение и начать новый запрос, а не отключать согласованность.
Характерный признак: Один процесс сделал COMMIT, другой продолжает видеть прежнее значение до завершения текущей транзакции либо после использования кэша приложения.
#Как отличить возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Долгая транзакция чтенияВ WAL SELECT видит один снимок до конца транзакции | Новый клиент видит обновление, старый — нет | Завершать транзакцию между запросами |
| Кэш приложенияПамять процесса или ORM хранит старую сущность | После перезапуска кэш сбрасывается | Настроить срок жизни/инвалидацию |
| Разные файлы SQLiteПриложения открыли разные .db | PRAGMA database_list показывает разные пути | Согласовать строку подключения |
#Пошаговая диагностика и исправление
- 1. Убедитесь, что запись была зафиксированаВ коде пишущего приложения проверьте успешный COMMIT после INSERT/UPDATE. Если транзакция откатана или процесс аварийно завершился, читатель закономерно не видит изменения.
- 2. Сравните пути двух подключенийНа каждом соединении выведите список присоединённых баз. Одинаковые логические имена ещё не доказывают один и тот же физический файл: сравнивайте абсолютные пути и окружение контейнера.
- Только чтениеLinux · Терминал (Bash)КомандаТолько чтение. В реальном приложении запустите PRAGMA на каждом соединении, а не только из отдельного sqlite3.
sqlite3 -readonly /srv/app/data/app.db 'PRAGMA database_list;'
- 3. Воспроизведите на отдельном тестовом файлеСначала в терминале Linux создайте новую учебную базу /tmp/sqlite-snapshot-demo.db (проверьте, что такого файла с данными нет). Затем откройте sqlite3 в двух отдельных терминалах на одном компьютере. В терминале A введите BEGIN; SELECT v FROM demo WHERE id=1; и ОСТАВЬТЕ транзакцию открытой. В B сделайте UPDATE из примера. После этого в A новый SELECT внутри той же транзакции вернёт old; введите COMMIT; и повторите SELECT — теперь ожидается new.
- Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
- 4. Проверьте, где в коде открывается транзакцияИщите ручной BEGIN, autocommit=False, ORM-сессии и курсоры, которые переживают один веб-запрос. В Python sqlite3 учитывайте особенности версий и режима autocommit; фиксируйте явный COMMIT/ROLLBACK при завершении логической операции.
- 5. Завершите старую транзакцию чтенияВ тестовом приложении завершите SELECT, закройте курсор и выполните COMMIT или ROLLBACK в зависимости от логики. Затем начните новый SELECT; в обычной схеме он должен увидеть новые зафиксированные строки.
- 6. Проверьте работу долгих фоновых заданийЕсли процесс читает миллион строк и держит транзакцию минуты, разбивайте выгрузку по логическим порциям, при этом учитывайте изменение данных между порциями. Для отчёта, которому нужен целостный снимок, старое отображение в течение транзакции является ожидаемым.
- 7. Исключите кэширование в приложенииНа тесте отключите только прикладной кэш конкретного запроса или выполните явное обновление ORM-сущности по инструкции используемой библиотеки. Если новая транзакция SQL показывает свежие данные, а интерфейс нет — проблема на уровне приложения.
- 8. Проверьте поведение после нового запросаВ тестовой среде сделайте две последовательные записи из отдельного клиента и убедитесь, что после завершения транзакции чтения новое подключение видит обе. Если результат не меняется, сравните время COMMIT и журналы приложения.
#Как проверить исправление
После завершения читающей транзакции и нового SELECT видна подтверждённая запись, при этом длительный отчёт продолжает последовательно видеть свой снимок.
#Если исправление не помогло
Если значение не обновилось, проверьте незафиксированную транзакцию писателя, другую базу, ORM-кэш, реплику на уровне приложения и ошибки сериализации.