Как остановить файл базы данных исключение заблокирован? - PullRequest
1 голос
/ 26 ноября 2009

У меня есть многопоточное приложение, которое использует sqlite. Когда два потока пытаются обновить БД одновременно, я получаю исключение

Additional information: The database file is locked

Я думал , что он попытается через несколько миллисекунд. Мои запросы не сложны. Наиболее сложным (что часто случается) является обновление, выбор, запуск тривиального обновления кода / удаление, фиксация. Почему это исключение? Как я могу заставить его повторить несколько раз, прежде чем выдать исключение?

Ответы [ 3 ]

3 голосов
/ 26 ноября 2009

SQLite не является потокобезопасным для доступа, поэтому вы получаете это сообщение об ошибке.

Вам следует синхронизировать доступ к базе данных (создать объект и «заблокировать» его) всякий раз, когда вы переходите к обновлению. Это приведет к блокировке второго потока и ожиданию автоматического завершения обновления первого потока.

1 голос
/ 26 ноября 2009

постарайтесь сделать ваши транзакции / коммиты максимально короткими. Единственный раз, когда вы можете заблокировать / заблокировать транзакцию - таким образом, если вы не сделаете их, у вас не возникнет проблемы.

Тем не менее, бывают случаи, когда вам нужно выполнять транзакции (в основном, при обновлении данных), но не делайте их, пока вы "запускаете тривиальный код", если можете этого избежать.

0 голосов
/ 26 ноября 2009

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

m_updateQueue.Add(()=>InsertOrder(o));

Тогда у вас может быть выделенный поток обновлений, который обрабатывает очередь.

Этот код будет выглядеть примерно так (я не скомпилировал и не протестировал его):

class UpdateQueue : IDisposable
{
     private object m_lockObj;
     private Queue<Action> m_queue;
     private volatile bool m_shutdown;
     private Thread m_thread;

     public UpdateQueue()
     {
         m_lockObj = new Object();
         m_queue = new Queue<Action>();
         m_thread = new Thread(ThreadLoop);
         m_thread.Start();
     }

     public void Add(Action a)
     {
         lock(m_lockObj)
         {
             m_queue.Enqueue(a);
             Monitor.Pulse(m_lockObj);
         }
     }

     public void Dispose()
     {
         if (m_thread != null)
         {
             m_shutdown = true;
             Monitor.PulseAll(m_lockObj);
             m_thread.Join();
             m_thread = null;
         }
     }

     private void ThreadLoop()
     {
         while (! m_shutdown)
         {
             Action a;
             lock (m_lockObj)
             {
                 if (m_queue.Count == 0)
                 {
                     Monitor.Wait(m_lockObj);
                 }

                 if (m_shutdown)
                 {
                     return;
                 }

                 a = m_queuue.Dequeue();
             }
             a();
         }
     }

}

Или вы могли бы использовать что-то кроме Sql Lite.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...