Подтвердить что ты не робот

База данных 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 для исправления.

4b9b3361

Ответ 1

Несколько вещей, которые следует учитывать:

  • Файлы DBite SQLite3 растут примерно в несколько раз по размеру страницы БД и не сжимаются, если вы не используете VACUUM. Если вы удалите несколько строк, освобожденное пространство будет помечено внутри и повторно использовано в последующих вставках. Поэтому вставка часто не вызывает изменения размера файла базы данных резервного копирования.

  • Вам не следует использовать традиционные средства резервного копирования для SQLite (или любой другой базы данных, если на то пошло), так как они не учитывают информацию состояния БД, которая имеет решающее значение для обеспечения неповрежденной базы данных. Особенно, копирование файлов DB в середине транзакции вставки - это рецепт катастрофы...

  • SQLite3 имеет API специально для резервного копирования или копирования используемых баз данных.

  • И да, похоже, что ваши файлы DB повреждены. Это может быть ошибка аппаратной/файловой системы. Или, может быть, вы скопировали их, пока они были в использовании? Или, возможно, восстановлена ​​резервная копия, которая не была должным образом взята?

Ответ 2

Чтобы восстановить поврежденную базу данных, вы можете использовать утилиту командной строки 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, которую я использую в качестве постоянного хранилища для Core Data, и при сохранении сохранялась следующая ошибка:

Не удалось сохранить: NSError 259 в домене NSCocoaErrorDomain {NSFilePath = mydata.db NSUnderlyingException = Фатальная ошибка. База данных на mydata.db поврежден. Код ошибки SQLite: 11, "образ диска базы данных искажен" }

Ответ 3

Я использую следующий script для исправления поврежденных файлов sqlite:

#!/bin/bash

cat <( sqlite3 "$1" .dump | grep "^ROLLBACK" -v ) <( echo "COMMIT;" ) | sqlite3 "fix_$1"

В большинстве случаев, когда база данных sqlite искажена, по-прежнему можно создать дамп. Этот дамп в основном представляет собой множество операторов SQL, которые перестраивают базу данных.

Некоторые строки могут отсутствовать в дампе (возможно, из-за их повреждения). Если это так, операторы INSERT отсутствующих строк будут заменены некоторыми комментариями, а script закончится с помощью ROLLBACK TRANSACTION.

Итак, что мы делаем здесь, мы делаем дамп (неверные строки исключены), и мы заменяем ROLLBACK на COMMIT, чтобы весь отвал script был отправлен вместо откат.

Этот метод спас мою жизнь уже в 100 раз уже\o/

Ответ 4

Чтобы избежать "полной загрузки базы данных или диска", попробуйте это, если у вас много ОЗУ:

sqlite> pragma temp_store = 2;

Это говорит SQLite, чтобы помещать временные файлы в память. (Сообщение "база данных или диск заполнено" не означает, что база данных заполнена или что диск заполнен! Это означает, что каталог temp заполнен.) У меня 256G оперативной памяти, но только 2G из /tmp, поэтому это работает отлично подходит для меня. Чем больше у вас RAM, тем больше файлов db вы можете работать.

Если у вас нет большого количества баранов, попробуйте следующее:

sqlite> pragma temp_store = 1;
sqlite> pragma temp_store_directory = '/directory/with/lots/of/space';

temp_store_directory устарел (что глупо, поскольку temp_store не устарел и требует temp_store_directory), поэтому будьте осторожны с его использованием в коде.

Ответ 5

Я видел, как это происходит, когда база данных повреждена, попробовали ли вы клонировать ее в новую?

Safley скопировать SQLite db

Безопасная копия базы данных SQLite

Тривиально легко скопировать базу данных SQLite. Это менее тривиально это так, что это не испортит его. Вот как:

shell$ sqlite3 some.db
sqlite> begin immediate;
<press CTRL+Z>
shell$ cp some.db some.db.backup
shell$ exit
sqlite> rollback;

Это даст вам хорошую чистую резервную копию, которая обязательно будет в правильном state, так как запись в базу данных на полпути через ваше копирование процесс невозможен.

Ответ 6

при использовании 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

после этого он наконец-то сработал.

Ответ 7

Если повреждение находится на первой странице, мы не можем использовать метод ".dump" для его восстановления.

Существует инструмент под названием undark, который экспортирует все строки (удаленные или нет) из файла db, если записи не были перезаписаны. Последняя версия здесь.

Я также использовал SQLite-Deleted-Records-Parser, но не выдавал тот же тип вывода.

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

  • litereplica - Репликация с одним мастером с восстановлением по времени
  • litesync - синхронизация с несколькими мастерами
  • rqlite - Репликация с несколькими мастерами

Или регулярно используйте Backup API. Хотя он переносит всю базу данных на каждую резервную копию.

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

Ответ 8

Клонирование текущей базы данных из командной строки sqlite3 мне помогло.

.open /path/to/database/corrupted_database.sqlite3
.clone /path/to/database/new_database.sqlite3

В файле настроек Django измените имя базы данных

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'new_database.sqlite3'),
}}

Ответ 9

Во время разработки приложения я обнаружил, что сообщения поступают из частых и массивных операций INSERT и UPDATE. Убедитесь, что INSERT и UPDATE несколько строк или данных за одну операцию.

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)