IoErr (10), сообщение = System.Data.SQLite.SQLiteException (0x800007FF): ошибка дискового ввода-вывода в System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn

Обратите внимание, что я запускаю приложение службы Windows, используя .NET Framework 4.6.2, и только иногда возникает эта ошибка:

2019-04-22 18:35:36.7727|ERROR|DataIntegrator.MyService|ERROR: code = IoErr (10), message = System.Data.SQLite.SQLiteException (0x800007FF): disk I/O error
disk I/O error
   at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
   at System.Data.SQLite.SQLiteCommand.BuildNextCommand()
   at System.Data.SQLite.SQLiteDataReader.NextResult()
   at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteHelper.Insert(String tableName, Dictionary`2 dic) in C:\Projects\DataIntegrator\DataIntegrator\DataAccessLayer\SQLiteHelper.cs:line 254
   at System.Data.SQLite.Insert.InsertTag(Tag tag) in C:\Projects\DataIntegrator\DataIntegrator\DataAccessLayer\Query\Insert.cs:line 60

Вот мой код с ошибкой, возникающей в строке sh.Insert:

    public static void InsertTag(Tag tag)
    {
        try
        {
            using (SQLiteConnection conn = new SQLiteConnection(Constants.DataSource))
            {
                using (SQLiteCommand cmd = new SQLiteCommand())
                {
                    cmd.Connection = conn;
                    conn.Open();

                    SQLiteHelper sh = new SQLiteHelper(cmd);

                    var dic = new Dictionary<string, object>();
                    dic["Id"] = tag.Id;
                    dic["Item"] = tag.Item;
                    dic["Value"] = tag.Value;
                    dic["Source"] = tag.Source;

                    sh.Insert(Constants.TagTable, dic);

                    conn.Close();
                }
            }
        }
        catch (Exception ex)
        {
            LogError("ERROR: {0}", ex.ToString());
        }
    }

У кого-нибудь есть предложения? Вот некоторые другие ссылки, которые я проверил, но еще не нашел решения:

SQLiteDiskIOException с кодом ошибки 10: ошибка дискового ввода-вывода

ошибка дискового ввода-вывода sqlite3 на cli

https://dba.stackexchange.com/questions/93575/sqlite-disk-io-error-3850

https://github.com/linuxserver/docker-sonarr/issues/38

https://forums.sonarr.tv/t/disk-io-and-sqllite-error/5578

В последнем упоминается, что база данных повреждена, но когда я останавливаю консольное приложение, я могу открыть базу данных. Должен ли я использовать другую базу данных, такую ​​как Berkeley DB, которая потенциально имеет более высокую производительность?

https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html

http://www.tsjensen.com/blog/post/2011/09/03/How+To+Get+Berkeley+DB+5228+And+NET+Examples+Working+In+Visual+Studio+2010+SP1

ОБНОВЛЕНИЕ:

Добавлены ОС в теги


person user8128167    schedule 23.04.2019    source источник
comment
Кажется, ошибка произошла SQLiteHelper.cs:line 254, а не InsertTag. InsertTag (Insert.cs:line 60) - это место, где вызывается SQLiteHelper.   -  person Olivier Jacot-Descombes    schedule 23.04.2019
comment
SQLite — это не сервер баз данных, предназначенный для обработки больших файлов. SQLite просто читает из файла на вашем ПК. Я бы порекомендовал использовать SQL Server (или Express), который вы можете бесплатно загрузить с msdn и который даст гораздо лучшую производительность, чем SQLite.   -  person jdweng    schedule 23.04.2019
comment
Спасибо за предложение - я только что добавил ОС. Обратите внимание, что я использую устройство с ограниченными ресурсами, поэтому добавление полного сервера базы данных, такого как SQL Server, невозможно. Кроме того, файлы, с которыми я имею дело, не слишком велики — около 100 МБ данных за пару дней.   -  person user8128167    schedule 23.04.2019
comment
Запуск через службу Windows; если вы также запускаете файл базы данных из общего сетевого ресурса, помните, что SQLite требует надежной блокировки файлов от ОС, и в прошлом были проблемы с сетевой блокировкой файлов Windows, которая не совсем устраивала.   -  person Mark Benningfield    schedule 23.04.2019
comment
@user8128167 user8128167, могу ли я подтвердить, что служба Windows в вашем сообщении означает основное приложение .net, размещенное как служба Windows? Или это фоновое приложение?   -  person Michael Xu - MSFT    schedule 24.04.2019
comment
Это .NET Framework 4.6.2, размещенный как служба Windows.   -  person user8128167    schedule 24.04.2019
comment
@user8128167 user8128167, насколько мне известно, Windows IoT Core не может запускать службу Windows, разработанную на C#. Не могли бы вы рассказать мне, как разместить службу Windows в Windows IoT Core?   -  person Michael Xu - MSFT    schedule 25.04.2019
comment
Извините, на самом деле у него Windows IoT Enterprise, а не Core.   -  person user8128167    schedule 25.04.2019
comment
@ user8128167, как упомянул Марк Беннингфилд, вы запускали файл базы данных из общего сетевого ресурса?   -  person Michael Xu - MSFT    schedule 26.04.2019
comment
Нет, это на диске C:\   -  person user8128167    schedule 26.04.2019


Ответы (1)


Обратите внимание, что изначально я использовал синхронный обработчик событий DataReceived, из-за которого ЦП сильно загружался и приводил к ошибкам дискового ввода-вывода:

    private readonly SerialPort _port = null;

    public MySerialPort(string comPortName)
    {
        ComPortName = comPortName;
        _port = new SerialPort(ComPortName,
            9600, Parity.None, 8, StopBits.One);
            _port.DataReceived -= new
                SerialDataReceivedEventHandler(port_DataReceived);
        _port.Open();
    }

    private void port_DataReceived(object sender,
        SerialDataReceivedEventArgs e)
    {
        SerialPort port = (SerialPort)sender;
        if (!port.IsOpen) return;

        for (int i = 0; i < port.BytesToRead; i++)
        {
            // process bytes
        }
    }

Чтобы повысить производительность и устранить ошибку диска ввода-вывода, я решил использовать асинхронный обработчик событий через базовый класс:

    private readonly SerialPort _port = null;

    public MySerialPort(string comPortName)
    {
        ComPortName = comPortName;
        _port = new SerialPort(ComPortName,
            9600, Parity.None, 8, StopBits.One);
         _port.Open();
         var rxData = Task.Run(async () => await ReceiveData());
        // ...
    }


public async Task<Stream> ReceiveData()
{
    var buffer = new byte[4096];
    int readBytes = 0;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        while ((readBytes = await _port.BaseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            memoryStream.Write(buffer, 0, readBytes);
        }

        return memoryStream;
    }

}

Подробнее см.

http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

а также

Правильная реализация асинхронного чтения последовательного порта

person user8128167    schedule 27.06.2019