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,'数据库磁盘映像格式错误'}
thk*_*ala 26
需要考虑的一些事项:
SQLite3数据库文件大致增长到数据库页面大小的倍数,除非您使用,否则不会收缩VACUUM.如果删除某些行,则释放的空间将在内部标记,并在以后的插入中重复使用.因此,插入通常不会导致后备DB文件的大小发生变化.
您不应该为SQLite(或任何其他数据库)使用传统备份工具,因为它们不会考虑对确保数据库未损坏至关重要的数据库状态信息.特别是,在插入事务中复制DB文件是一个灾难的秘诀......
SQLite3有一个专门用于备份或复制正在使用的数据库的API.
是的,似乎您的数据库文件已损坏.它可能是硬件/文件系统错误.或许你在使用它们时复制它们?或者可能还原了未正确使用的备份?
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 /
为了避免首先"数据库或磁盘已满",如果你有大量的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),所以要小心在代码中使用它.
小智 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)
我已经看到当数据库损坏时会发生这种情况,您是否尝试将其克隆到新数据库中?
安全地复制SQLite数据库
复制SQLite数据库非常容易.以不会破坏它的方式做这件事并不是那么简单.这是如何做:
Run Code Online (Sandbox Code Playgroud)shell$ sqlite3 some.db sqlite> begin immediate; <press CTRL+Z> shell$ cp some.db some.db.backup shell$ exit sqlite> rollback;这将为您提供一个很好的干净备份,确保处于正确的状态,因为在复制过程的中途写入数据库是不可能的.