SQLite3数据库或磁盘已满/数据库磁盘映像格式错误

jef*_*unt 50 filesystems sqlite file corruption

我的数据库大约是25 MB,我已经确认访问它的用户名以及文件权限在几个月内没有变化.我遇到问题,由于"数据库或磁盘已满",查询失败,有时"数据库磁盘映像格式错误"问题.

除非我读错了,否则我的磁盘不会接近满(这是一个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
Run Code Online (Sandbox Code Playgroud)

作为一个测试,我刚刚做了一个添加了新记录的动作,这很好.我试图确定是否有一组特定的失败行动.但是,在插入(并验证它在那里)之后,磁盘上数据库的字节数没有改变(既不向上也不向下).

使用命令行实用程序会产生类似下面的内容,这会非常失败:)

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. ...
Run Code Online (Sandbox Code Playgroud)

关于我接下来要去哪里的任何想法?表中的最大行数是否存在问题?我对SQLite3最大值进行了一些阅读,据我所知,我的数据库中没有任何内容与它们有任何关系.

然后我查看了我的每日备份,我发现数据库备份的文件大小没有改变3-4天 - 非常奇怪.我在文件大小没有变化之前恢复了数据库的备份副本,但仍然遇到了奇怪的问题.

我想我将不得不(1)从旧备份恢复,(2)重新运行我的Rails迁移来修复.

Peg*_*lon 55

要修复损坏的数据库,可以使用sqlite3命令行实用程序.在设置环境变量后,在shell中键入以下命令:

cd $DATABASE_LOCATION
echo '.dump'|sqlite3 $DB_NAME|sqlite3 repaired_$DB_NAME
mv $DB_NAME corrupt_$DB_NAME
mv repaired_$DB_NAME $DB_NAME
Run Code Online (Sandbox Code Playgroud)

这段代码帮助我恢复了一个SQLite数据库,我将其用作Core Data的持久存储,并在保存时产生以下错误:

无法保存:域NSCocoaErrorDomain中的NSError 259 {NSFilePath = mydata.db NSUnderlyingException =致命错误.mydata.db上的数据库已损坏.SQLite错误代码:11,'数据库磁盘映像格式错误'}

  • 您也可以只使用 .clone newdb.sqlite (3认同)
  • 这里它生成一个 0 字节的输出文件。转储到 .sql 将返回“ROLLBACK”,最后一行为“由于错误”注释。 (3认同)
  • 谢谢你一百万次 - 我花了几个小时创建了一个核心数据数据库,该数据库出现错误代码 11 问题(在 iOS 4.3 中,但由于某种原因不在 4.2 中)并且无法加载,而是转储到新创建的数据库中,例如这解决了这个问题。是的! (2认同)
  • 我遇到了类似的问题,这为我指明了正确的方向,但仅仅进行转储还不够......它生成了一个 0 字节的新 sqlite 文件。我必须首先将 sql 文件转储到文本文件中,然后删除一些明显来自 sqlite 系统的带有“错误”的行,然后使用该文本文件的 sql 创建一个 sqlite 文件。这对我有用。 (2认同)

thk*_*ala 26

需要考虑的一些事项:

  • SQLite3数据库文件大致增长到数据库页面大小的倍数,除非您使用,否则不会收缩VACUUM.如果删除某些行,则释放的空间将在内部标记,并在以后的插入中重复使用.因此,插入通常不会导致后备DB文件的大小发生变化.

  • 您不应该为SQLite(或任何其他数据库)使用传统备份工具,因为它们不会考虑对确保数据库未损坏至关重要的数据库状态信息.特别是,在插入事务中复制DB文件是一个灾难的秘诀......

  • SQLite3有一个专门用于备份或复制正在使用的数据库的API.

  • 是的,似乎您的数据库文件已损坏.它可能是硬件/文件系统错误.或许你在使用它们时复制它们?或者可能还原了未正确使用的备份?

  • 为了社区的利益,我使用此处概述的方法修复/恢复数据库:http://community.spiceworks.com/how_to/show/1468我也有每日备份,所以这个潜在的'哦sh*时刻变成了一个相对较小的中断. (5认同)
  • 鉴于我看到的症状,它看起来像#3(备份正在使用的数据库的副本)。分页大小/数据库大小按照您的描述方式非常合理。所以,我正在尝试修复它,或者从通过完整性检查的每日备份副本中恢复(谢天谢地,我有一个),然后更改我的备份方案。 (2认同)

Elm*_*mer 21

我使用以下脚本来修复格式错误的sqlite文件:

#!/bin/bash

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

大多数情况下,当sqlite数据库格式错误时,仍然可以进行转储.这个转储基本上是很多重建数据库的SQL语句.

转储中可能缺少某些行(可能是因为它们已损坏).如果是这种情况,缺失行的INSERT语句将被替换为一些注释,脚本将以ROLLBACK TRANSACTION结束.

所以我们在这里做的是我们进行转储(排除格式错误的行),然后用COMMIT替换ROLLBACK,这样就可以提交整个转储脚本而不是回滚.

这种方法已经节省了我几百次的生命\ o /


Phi*_*etz 9

为了避免首先"数据库或磁盘已满",如果你有大量的RAM,请尝试这样做:

sqlite> pragma temp_store = 2;
Run Code Online (Sandbox Code Playgroud)

这告诉SQLite将临时文件放在内存中.("数据库或磁盘已满"消息并不意味着数据库已满或磁盘已满!这意味着临时目录已满.)我有256G的RAM但只有2G的/ tmp,所以这个工作原理对我很好.您拥有的RAM越多,您可以使用的db文件越大.

如果你没有很多ram,试试这个:

sqlite> pragma temp_store = 1;
sqlite> pragma temp_store_directory = '/directory/with/lots/of/space';
Run Code Online (Sandbox Code Playgroud)

不推荐使用temp_store_directory(这很愚蠢,因为temp_store不被弃用且需要temp_store_directory),所以要小心在代码中使用它.

  • 我在 /tmp 中有很多似乎没有使用的磁盘空间。我正在创建一个临时表,导致抛出“数据库或磁盘已满”错误。设置`temp_store` 使用内存解决了这个问题。我有 3GB 的内存和 1.6GB 的 /tmp。 (2认同)

小智 6

从 sqlite3 命令行克隆当前数据库对我有用。

.open /path/to/database/corrupted_database.sqlite3
.clone /path/to/database/new_database.sqlite3
Run Code Online (Sandbox Code Playgroud)

在 Django 设置文件中更改数据库名称

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

  • 事实上,克隆对我来说比“.dump”效果更好。 (2认同)

Nix*_*Nix 5

我已经看到当数据库损坏时会发生这种情况,您是否尝试将其克隆到新数据库中?

Safley复制为SQLite数据库

安全地复制SQLite数据库

复制SQLite数据库非常容易.以不会破坏它的方式做这件事并不是那么简单.这是如何做:

shell$ sqlite3 some.db
sqlite> begin immediate;
<press CTRL+Z>
shell$ cp some.db some.db.backup
shell$ exit
sqlite> rollback;
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个很好的干净备份,确保处于正确的状态,因为在复制过程的中途写入数据库是不可能的.