我的数据库大约是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
作为测试,我刚刚做了一个添加了新记录的动作,这很好。我试图确定是否有一组特定的失败行动。但是,在插入(并验证它在那里)之后,磁盘上数据库的字节数没有改变(既不向上也不向下)。
使用命令行实用程序会产生如下所示的内容,这种情况非常糟糕:)
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最大值进行了一些阅读,据我所知,我的数据库中没有任何内容与它们有任何关系。
然后我查看了我的每日备份,我发现数据库备份的文件大小没有改变3-4天 - 非常奇怪。我在文件大小没有变化之前恢复了数据库的备份副本,但仍然遇到了奇怪的问题。
我想我将不得不(1)从旧备份恢复,(2)重新运行我的Rails迁移来修复。
答案 0 :(得分:50)
要修复损坏的数据库,您可以使用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
此代码帮助我恢复了一个SQLite数据库,我将其用作Core Data的持久存储,并在保存时产生以下错误:
无法保存:域中的NSError 259 NSCocoaErrorDomain {NSFilePath = mydata.db NSUnderlyingException = 致命错误。 mydata.db上的数据库 已经腐败了。 SQLite错误代码:11, '数据库磁盘映像格式错误'}
答案 1 :(得分:24)
需要考虑的一些事项:
答案 2 :(得分:18)
我使用以下脚本修复格式错误的sqlite文件:
#!/bin/bash
cat <( sqlite3 "$1" .dump | grep "^ROLLBACK" -v ) <( echo "COMMIT;" ) | sqlite3 "fix_$1"
大多数情况下,当sqlite数据库格式错误时,仍然可以进行转储。这个转储基本上是很多重建数据库的SQL语句。
转储中可能缺少某些行(可能是因为它们已损坏)。如果是这种情况,缺失行的INSERT语句将被替换为一些注释,脚本将以ROLLBACK TRANSACTION结束。
所以我们在这里做的是我们进行转储(排除格式错误的行),然后用COMMIT替换ROLLBACK,以便提交整个转储脚本而不是回滚。
这种方法已经为我的生命节省了几百次\ o /
答案 3 :(得分:9)
为了避免首先“数据库或磁盘已满”,如果你有大量的RAM,请尝试这样做:
sqlite> pragma temp_store = 2;
告诉SQLite将临时文件放在内存中。 (“数据库或磁盘已满”消息并不意味着数据库已满或磁盘已满!这意味着临时目录已满。)我有256G的RAM但只有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),所以要小心在代码中使用它。
答案 4 :(得分:5)
我已经看到当数据库损坏时会发生这种情况,您是否尝试将其克隆到新数据库中?
安全地复制SQLite数据库
复制SQLite数据库非常容易。这样做不那么简单 这种方式不会破坏它。方法如下:
shell$ sqlite3 some.db sqlite> begin immediate; <press CTRL+Z> shell$ cp some.db some.db.backup shell$ exit sqlite> rollback;
这将为您提供一个很好的干净备份,肯定是正确的 状态,因为通过复制中途写入数据库 过程是不可能的。
答案 5 :(得分:3)
从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'),
}}
答案 6 :(得分:1)
在使用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 :(得分:0)
在应用程序开发期间,我发现消息来自频繁且大量的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)