База данных SQLite3 или диск заполнены / образ диска базы данных искажен
моя база данных составляет около 25 МБ, и я проверил, что имя пользователя, обращающееся к ней, а также права доступа к файлам не менялись в течение нескольких месяцев. У меня проблема, когда запросы терпят неудачу из-за "базы данных или диска заполнены", а затем иногда "образ диска базы данных искажен".
Если я не читаю это неправильно, мой диск нигде не заполнен (это сервер Ubuntu, 9.10, если это имеет значение)
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 19610300 2389596 16224560 13% /
udev 10240 128 10112 2% /dev
none 254136 0 254136 0% /dev/shm
none 254136 36 254100 1% /var/run
none 254136 0 254136 0% /var/lock
none 254136 0 254136 0% /lib/init/rw
в качестве теста я сделал действие, которое добавила новый рекорд, и все в порядке. Я пытаюсь выяснить, есть ли определенный набор действий, которые терпят неудачу. Однако после вставки (и проверки того, что она есть) количество байтов на диске для базы данных не изменилось (ни вверх, ни вниз).
использование утилиты командной строки приводит к чему-то вроде следующего, что эффектно терпит неудачу :)
SQLite version 3.6.12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> pragma integrity_check;
*** in database main ***
On tree page 2 cell 0: 2nd reference to page 26416
On tree page 2 cell 1: 2nd reference to page 26417
On tree page 2 cell 2: 2nd reference to page 26434
On tree page 2 cell 3: 2nd reference to page 26449
On tree page 2 cell 4: 2nd reference to page 26464
On tree page 2 cell 5: 2nd reference to page 26358
On tree page 2 cell 6: 2nd reference to page 26494
On tree page 2 cell 7: Child page depth differs
On tree page 2 cell 8: 2nd reference to page 26190
On tree page 2 cell 8: Child page depth differs
... etc., etc. ...
есть идеи, где я должен искать дальше? Есть проблема с максимальным количеством строки в таблице или что? Я прочитал некоторые значения sqlite3 max, и, насколько я могу судить, в моей базе данных нет ничего близкого к ним.
затем я посмотрел на свои ежедневные резервные копии, и я вижу, что резервная копия базы данных не изменилась в размере файла в течение 3-4 дней - очень странно. Я восстановил резервную копию базы данных до того, как она не изменилась в размере файла, и все еще получаю странные проблемы.
Я думаю, что мне придется (1) восстановить из старая резервная копия и (2) Повторите миграцию Rails для исправления.
7 ответов
несколько вещей, чтобы рассмотреть:
файлы БД SQLite3 растут примерно кратно размеру страницы БД и не сжимаются, если вы не используете
VACUUM
. При удалении некоторых строк освобожденное пространство помечается внутри и повторно используется в последующих вставках. Поэтому вставка часто не приводит к изменению размера файла БД.вы не должны использовать традиционные инструменты резервного копирования для SQLite (или любой другой базы данных, если на то пошло), так как они делают не принимать во внимание информацию о состоянии БД, которая имеет решающее значение для обеспечения неповрежденной базы данных. Особенно, копирование файлов БД в середине транзакции вставки-это рецепт катастрофы...
и sqlite3 имеет API специально для резервного копирования или копирования баз данных, которые используются.
и да, кажется, что ваши файлы БД являются повреждены. Это может быть ошибка оборудования/файловой системы. Или, может быть, вы скопировал их, пока они были в использовании? Или, может быть, восстановил резервную копию, которая была неправильно взята?
для восстановления поврежденной базы данных можно использовать утилиту командной строки sqlite3. После установки переменных среды введите в оболочке следующие команды:
cd $DATABASE_LOCATION
echo '.dump'|sqlite3 $DB_NAME|sqlite3 repaired_$DB_NAME
mv $DB_NAME corrupt_$DB_NAME
mv repaired_$DB_NAME $DB_NAME
этот код помог мне восстановить базу данных SQLite, которую я использую как постоянное хранилище для основных данных и которая вызвала следующую ошибку при сохранении:
не удалось сохранить: NSError 259 в домене NSCocoaErrorDomain { NSFilePath = файл mydata.db NSUnderlyingException = Фатальная ошибка. База данных в файл mydata.децибел испорчен. Код ошибки SQLite: 11, "образ диска базы данных искажен"}
Я использую следующий скрипт для восстановления деформированных файлов sqlite:
#!/bin/bash
cat <( sqlite3 "" .dump | grep "^ROLLBACK" -v ) <( echo "COMMIT;" ) | sqlite3 "fix_"
большую часть времени, когда база данных sqlite искажена, все еще можно сделать дамп. Этот дамп-это в основном много операторов SQL, которые перестраивают базу данных.
некоторые строки могут отсутствовать в дампе (возможно, потому, что они повреждены). Если это так, инструкции INSERT отсутствующих строк будут заменены некоторыми комментариями, и скрипт закончится инструкция ROLLBACK Transaction.
Итак, что мы делаем здесь, мы делаем дамп (искаженные строки исключены), и мы заменяем откат фиксацией, чтобы весь сценарий дампа был зафиксирован вместо отката.
этот метод спас мне жизнь пару 100 раз уже \o/
чтобы избежать получения "база данных или диск заполнен" в первую очередь, попробуйте это, если у вас много ОЗУ:
sqlite> pragma temp_store = 2;
это говорит SQLite поместить временные файлы в память. (Сообщение "база данных или диск заполнены" не означает, что база данных заполнена или что диск заполнен! Это означает, что каталог temp заполнен.) У меня есть 256G ОЗУ, но только 2G /tmp, поэтому это отлично работает для меня. Чем больше у вас ОЗУ, тем больше файлов БД вы можете работать.
Если вы не получил много ОЗУ, попробуйте это:
sqlite> pragma temp_store = 1;
sqlite> pragma temp_store_directory = '/directory/with/lots/of/space';
temp_store_directory устарел (что глупо, так как temp_store не устарел и требует temp_store_directory), поэтому будьте осторожны с использованием этого в коде.
Я видел, как это происходит, когда база данных повреждена, вы пытались клонировать ее в новую ?
безопасное копирование базы данных SQLite
скопировать базу данных SQLite тривиально легко. Это менее тривиально. так, чтобы не испортить его. Вот как:
shell$ sqlite3 some.db sqlite> begin immediate; <press CTRL+Z> shell$ cp some.db some.db.backup shell$ exit sqlite> rollback;
Это даст вам хорошую чистую резервную копию, которая обязательно будет в правильном государство, с момента написания база данных на полпути через копирование процесс невозможен.
при использовании Google App Engine у меня была эта проблема. По какой-то причине я сделал следующее С тех пор Google App Engine никогда не запускался.
$ echo '' > /tmp/appengine.apprtc.root/*.db
чтобы исправить это, мне нужно было сделать вручную:
$ sqlite3 datastore.db
sqlite> begin immediate;
<press CTRL+Z>
$ cp datastore.db logs.db
а затем запустите Google App Engine с флагом:
$ dev_appserver.py --clear_datastore --clear_search_index
после этого он, наконец, работал.
во время разработки приложений я обнаружил, что сообщения поступают от частых и массовых операций вставки и обновления. Не забудьте вставить и обновить несколько строк или данных за одну операцию.
var updateStatementString : String! = ""
for item in cardids {
let newstring = "UPDATE "+TABLE_NAME+" SET pendingImages = '\(pendingImage)\' WHERE cardId = '\(item)\';"
updateStatementString.append(newstring)
}
print(updateStatementString)
let results = dbManager.sharedInstance.update(updateStatementString: updateStatementString)
return Int64(results)