LINUX.ORG.RU

SQLite 3.51.3 с исправлением возможного повреждения базы данных в режиме WAL

 , ,

SQLite 3.51.3 с исправлением возможного повреждения базы данных в режиме WAL

0

2

13-го марта состоялся корректирующий выпуск 3.51.3 компактной встраиваемой СУБД SQLite. Код проекта написан на языке C и распространяется как общественное достояние (public domain).

В связи с проблемами обратной совместимости, связанными с некоторыми новыми функциями, версия 3.52.0 (вышедшая 6-го марта) была отозвана.

Список изменений версии 3.51.3:

  • 3-го марта один из разработчиков SQLite (Dan) обнаружил и устранил ошибку, которая в редких случаях могла приводить к повреждению базы данных и названная «WAL-reset bug»:
    • Эта ошибка возникает только в базах данных, работающих в режиме WAL, если к одному и тому же файлу открыто два и более подключения в разных потоках или процессах, и если эти два подключения пытаются выполнить запись или создать контрольную точку одновременно.
    • Ошибка связана с конфликтом доступа к данным при жёстких временных ограничениях. В обычных условиях эксплуатации она возникает крайне редко. Разработчикам так и не удалось воспроизвести эту ошибку в естественных условиях, и им пришлось добавить в SQLite специальную логику тестирования, которая намеренно создает условия для возникновения ошибки, чтобы убедиться в том, что проблема устранена.
    • Ошибка возникает, когда:
      1. Одно соединение выполняет проверку контрольной точки. Эта первая проверка должна быть завершена. Другими словами, в ходе проверки необходимо успешно скопировать всё содержимое файла WAL обратно в базу данных и привести файл WAL в состояние, при котором его можно будет сбросить.
      2. Сразу после завершения работы первой контрольной точки запускается вторая.
      3. Пока запускается вторая контрольная точка из шага 2, другое подключение к базе данных фиксирует транзакцию, которая сбрасывает файл WAL и записывает новое содержимое в начало файла WAL.
      4. Из-за конфликта доступа к данным вторая контрольная точка из шага 2 не учитывает, что файл WAL был сброшен в результате фиксации транзакции на шаге 3. Вторая контрольная точка устанавливает неверное значение для одного из полей в заголовке индекса WAL. Это поле указывает, что часть файла WAL уже была зафиксирована в контрольной точке, хотя на самом деле это не так.
      5. Фиксация дополнительных транзакций приводит к увеличению количества страниц в файле WAL, которое превышает количество страниц, существовавшее на момент первой контрольной точки из шага 1.
      6. Позже, когда возникает третья контрольная точка, она пропускает всю или часть транзакции, записанной на этапе 3. Таким образом, части транзакции с этапа 3 так и не попадают в файл базы данных, в результате чего файл базы данных повреждается.
    • Ошибка, вероятно, присутствует во всех версиях SQLite, начиная с 3.7.0 (21.07.2010) и заканчивая 3.51.2. Также выпущены исправления для некоторых более ранних версий: 3.44.6 и 3.50.7.
  • Другие незначительные исправления.

>>> Страница загрузки

>>> Подробности на sqlite.org

★★★★★

Проверено: shell-script ()
Последнее исправление: dataman (всего исправлений: 2)

Я просто ещё раз напоминаю, почему ошибки в многопоточных-многопроцессовых-распределённых системах невозможно отследить тестированием. 15 лет софтина крутилась в проде с багом, и наверняка все происходящие ошибки списывались на «повреждение накопителя».

Варианта два: либо вычитывать сорцы и формально доказывать корректность логики; либо ставить палки во все потенциальные гонки, чтобы логика проводила в них 20% времени, как не 0.001% как обычно.

byko3y ★★★★
()

если к одному и тому же файлу открыто два и более подключения в разных потоках или процессах

…то не надо пытаться из хорошей работающей локальной СУБД делать убогое и калечное подобие клиент-серверной! Одного Access-a должно было хватить, чтобы это понять, зачем ещё SQLite во второй Access превращать?

Нужно несколько клиентов – берите хоть Марию, хоть Постгрю, для эстетов :) есть Firebird. Если хочется масштабируемости – есть разные рабочие способы обеспечить работу с разными СУБД в одном проекте. Из открытых примеров назову, например, OpenSimulator, там есть поддержка SQLite и трёх клиент-серверных продуктов (два из них, правда, родственники, но тем не менее).

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)
Ответ на: комментарий от hobbit

делать убогое и калечное подобие клиент-серверной!

Не удивлюсь, если очень многие используют многотопоточную запись в базы SQLite, когда хватило бы и KVDB, которых достаточно много.

dataman ★★★★★
() автор топика
Ответ на: комментарий от hobbit

Бывает нужно, чтобы БД была в том же процессе.
Что касается многопоточного доступа, то это решается внешними RWLock`ами. Полагатся на встроеные блокировки SQLite не стоит.

MirandaUser2 ★★
()
Ответ на: комментарий от hobbit

…то не надо пытаться из хорошей работающей локальной СУБД делать убогое и калечное подобие клиент-серверной! Одного Access-a должно было хватить, чтобы это понять, зачем ещё SQLite во второй Access превращать?

Ну всё-таки MS Access работает по совершенно иной архитектуре многопользователя. SQLite чисто теоретически полностью блокирует БД при записи, но есть ньюанс...

Нужно несколько клиентов – берите хоть Марию, хоть Постгрю, для эстетов :) есть Firebird.

Мы брали. Я не особо впечатлён был. Довольно часто возникают задачи full scan, которые через сетевой слой плохо пропихиваются, нужно так или иначе расширять серверную часть, чтобы меньше гонять по сети.

Как ни странно, модель эксклюзивной блокировки работает намного быстрее в однопользовательском режиме. MVCC СУБД с транзакциями нужны для длительно выполняющихся пишущих транзакций — если у вас таких нет, то зачем вам мария?

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

byko3y ★★★★
()

тут просто отсутствие понимания как в мультитредах работать или реально разрабов ткнули в их говно. или single process - single database не взлетело, что сомнительно.

etwrq ★★★★★
()
Ответ на: комментарий от etwrq

тут просто отсутствие понимания как в мультитредах работать или реально разрабов ткнули в их говно. или single process - single database не взлетело, что сомнительно.

Оно-то круто звучит — держать блокировку несколько секунд, пока вся запись на диск не закончится, но в реальной жизни такой профиль очень неприятен в эксплуатации. Попытались оптимизировать — получили неожиданные гонки.

Для справки, я напоминаю, что хоть в WAL, хоть в Rollback log режиме запись в БД — это не просто один write, это большой и сложный процесс.

byko3y ★★★★
()

версия 3.52.0 (вышедшая 6-го марта) была отозвана.

Скачавшие её были вычислены по IP и расстреляны.

BydymTydym ★★
()
Ответ на: комментарий от byko3y

15 лет софтина крутилась в проде с багом, и наверняка все происходящие ошибки списывались на «повреждение накопителя».

Конкурентная запись в sqlite отродясь хреново работает, хоть с wal хоть без него. Поэтому вероятность дойти до прода у такого решения на несколько порядков ниже, чем наткнуться на этот конкретный баг.

Lucky ★★
()
Последнее исправление: Lucky (всего исправлений: 1)

Яркий пример, как некорректные системы тем не менее генерят прибыль.

seiken ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.