一段时间后遇到Sqlite3磁盘I / O错误,但在使用db副本后有效 [英] Sqlite3 Disk I/O error encountered after a while, but worked after using copy of db

查看:768
本文介绍了一段时间后遇到Sqlite3磁盘I / O错误,但在使用db副本后有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用sqlite3数据库每秒记录一次数据。它的接口由Flask-SQLAlchemy提供。

I'm using an sqlite3 database to record data every second. The interface to it is provided by Flask-SQLAlchemy.

这可以正常工作几个月,但是最终(由于.db文件接近8 GB),错误导致无法将更多数据写入数据库:

提交失败:(sqlite3.OperationalError)磁盘I / O错误

This can work fine for a couple of months, but eventually (as the .db file approaches 8 GB), an error prevents any more data from being written to the database:
Failed to commit: (sqlite3.OperationalError) disk I/O error

日志文件似乎不是这里的问题-如果我重新启动应用程序并使用编译指示 journal_mode = TRUNCATE ,则会创建日志文件,但磁盘I / O错误仍然存在。

The journal file does not seem to be the issue here - if I restart the application and use the pragma journal_mode=TRUNCATE, the journal file is created but the disk I/O error persists.

.dbinfo(从sqlite3.exe获取):

Here's the .dbinfo (obtained from sqlite3.exe):

database page size:  1024
write format:        1
read format:         1
reserved bytes:      0
file change counter: 5200490
database page count: 7927331
freelist page count: 0
schema cookie:       12
schema format:       4
default cache size:  0
autovacuum top root: 0
incremental vacuum:  0
text encoding:       1 (utf8)
user version:        0
application id:      0
software version:    3008011
number of tables:    6
number of indexes:   7
number of triggers:  0
number of views:     0
schema size:         5630
data version         2

但是这可行:


  1. 我制作了.db文件的副本(调用app.db和copy.db)。

  2. I将app.db重命名为orig.db

  3. 我将copy.db重命名为app.db(如此有效,我将其交换以使副本成为应用程序)。

当我再次启动应用程序时,它能够再次写入app.db文件!这样我就可以写入数据库的副本了。

When I started my application again, it was able to write to the app.db file once more! So I could write to a copy I made of the database.

驱动器是SSD(三星850 EVO mSATA)>我想知道这是否与它有关?有谁对如何防止它再次发生有任何想法?

The drive is an SSD (Samsung 850 EVO mSATA)> I wonder if that's got something to do with it? Does anyone have any ideas on how I can prevent it from happening again?

编辑:我已经使用sqlite3.exe CLI手动执行了INSERT INTO命令,并且这实际上已成功完成(并已写入磁盘)。但是,当我重新运行Flask-SQLAlchemy接口进行写入时,它仍然出现磁盘I / O错误。

I've used the sqlite3.exe CLI to execute an INSERT INTO command manually, and this actually completed successfully (and wrote to the disk). However, when I re-ran my Flask-SQLAlchemy interface to write to it, it still came up with the disk I/O error.

推荐答案

更新:



一位同事指出,这可能与另一个问题有关:https://stackoverflow.com/a/49506243/3274353

我强烈怀疑这是文件系统问题-在我的系统中,数据库文件会不断更新,同时也会写入其他文件。

I strongly suspect now that this is a filesystem issue - in my system, the database file is being updated constantly alongside some other files which are also being written to.

因此,为了减少碎片数量,我正在将数据库-使用上述问题中提供的答案分配一些磁盘空间: https://stackoverflow.com/a/49506243/3274353

So to reduce the amount of fragmentation, I'm getting the database to pre-allocate some disk space now using the answer provided in aforementioned question: https://stackoverflow.com/a/49506243/3274353

类似这样的东西:

CREATE TABLE t(x);
INSERT INTO t VALUES(zeroblob(500*1024*1024));  -- 500 MB
DROP TABLE t;

要知道是否需要执行此操作,请使用 freelist_count pragma

To know whether this needs to be done, I use a call to the freelist_count pragma:


PRAGMA schema.freelist_count;

返回数据库文件中未使用的页数。

PRAGMA schema.freelist_count;
Return the number of unused pages in the database file.

这篇关于一段时间后遇到Sqlite3磁盘I / O错误,但在使用db副本后有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆