Файл базы данных необъяснимо заблокирован во время фиксации SQLite

Я не вижу большой нагрузки, которой Вы требуете от проверки входящего дюйм/с Наоборот, я сделал проект для одного из моих клиентов, который анализирует журналы доступа HTTP каждые пять минут (это, возможно, было в реальном времени, но он не хотел это по некоторым причинам, что я никогда полностью понял), и создает правила брандмауэра заблокировать соединения от любых IP-адресов, которые генерируют чрезмерное количество запросов, если адрес не может быть подтвержден как принадлежащий законной поисковой системе (Google, Yahoo, и т.д.).

Этот клиент выполняет услугу веб-хостинга и запускает это приложение на трех серверах, которые обрабатывают в общей сложности 800-900 доменов. Пиковое действие находится в диапазоне thousand-hits-per-second и никогда не было проблемы производительности - брандмауэры очень эффективны при отбрасывании пакетов от помещенных в черный список адресов.

И, да, технология DDOS определенно существует, который победил бы эту схему, но он не видит, что происходят в реальном мире. Наоборот, он говорит, что это значительно уменьшило нагрузку на его серверы.

10
задан Brian Sweeney 13 August 2009 в 00:07
поделиться

8 ответов

Запустите Sysinternals Process Monitor и отфильтруйте имя файла при запуске вашей программы, чтобы исключить, делает ли какой-либо другой процесс что-либо с ним, и посмотреть, что именно ваша программа делает с файл. Длинный выстрел, но может дать ключ к разгадке.

5
ответ дан 3 December 2019 в 14:34
поделиться

На что следует обратить внимание:

  • не используйте соединения между несколькими потоками / процессами.

  • Я видел, как это происходило, когда антивирусный сканер обнаруживал изменения в файле и пытался сканировать это. Это заблокирует файл на короткий промежуток времени и вызовет хаос.

3
ответ дан 3 December 2019 в 14:34
поделиться

Является ли ваш файл базы данных на том же компьютере, что и приложение, или он хранится на сервере?

Вы должны создавать новое соединение в каждом потоке. Я бы упростил создание соединения, использовал везде: connection = new SQLiteConnection (connString.ToString ());

и использовал файл базы данных на том же компьютере, что и приложение, и снова протестировал.

Почему используются два разных способа создания соединения?

2
ответ дан 3 December 2019 в 14:34
поделиться

У этих парней были похожие проблемы (в основном, похоже, с заблокированным файлом журнала, возможно, взаимодействия TortoiseSVN ... проверьте статьи, на которые есть ссылки).

Они предложили набор рекомендаций (правильные каталоги, изменение типов ведения журнала с удаления на сохранение и т. Д.). http://sqlite.phxsoftware.com/forums/p/689/5445.aspx#5445


Параметры режима журнала обсуждаются здесь: http://www.sqlite.org/pragma. html . Вы можете попробовать TRUNCATE.

Есть ли трассировка стека во время исключения в SQL Lite?

Вы указываете, что вы «пакетируете мои коммиты с разумным интервалом». Какой интервал?

2
ответ дан 3 December 2019 в 14:34
поделиться

Похоже, вам не удалось связать команду с созданной вами транзакцией. . Вместо:

using (SQLiteCommand command = conn.CreateCommand())

Вы должны использовать:

using (SQLiteCommand command = new SQLiteCommand("<INSERT statement here>", conn, trans))

Или вы можете установить его свойство Transaction после его создания.

Пока мы занимаемся этим - ваша обработка сбоев неверна:

Метод ExecuteNonQuery команды также может дать сбой и вы действительно не защищены. Вам следует изменить код на что-то вроде:

   public void Commit()
    {
        using (SQLiteConnection conn = new SQLiteConnection(this.connString))
        {
            conn.Open();
            SQLiteTransaction trans = conn.BeginTransaction();
            try
            {
                using (SQLiteCommand command = conn.CreateCommand())
                {
                    command.Transaction = trans; // Now the command is linked to the transaction and don't try to create a new one (which is probably why your database gets locked)
                    command.CommandText = "INSERT OR IGNORE INTO [MY_TABLE] (col1, col2) VALUES (?,?)";

                    command.Parameters.Add(this.col1Param);
                    command.Parameters.Add(this.col2Param);

                    foreach (Data o in this.dataTemp)
                    {
                        this.col1Param.Value = o.Col1Prop;
                        this. col2Param.Value = o.Col2Prop;

                        command.ExecuteNonQuery();
                    }
                }

                trans.Commit();
            }
            catch (SQLiteException ex)
            {
                // You need to rollback in case something wrong happened in command.ExecuteNonQuery() ...
                trans.Rollback();
                throw;
            }
        }
    }

Другое дело, что вам не нужно ничего кэшировать в памяти. Вы можете положиться на механизм ведения журнала SQLite для сохранения неполного состояния транзакции.

9
ответ дан 3 December 2019 в 14:34
поделиться

Я бы всегда использовал соединение, транзакцию и команду в предложении using . В первом листинге кода вы это сделали, а в третьем (создание таблиц) - нет. Я предлагаю вам сделать это тоже, потому что (кто знает?), Возможно, команды, которые создают таблицу, каким-то образом продолжают блокировать файл. Дальний выстрел ... но стоит ли выстрел?

2
ответ дан 3 December 2019 в 14:34
поделиться

У вас запущен Google Desktop Search (или другой индексатор файлов)? Как упоминалось ранее, Sysinternals Process Monitor может помочь вам отследить его.

Кроме того, каково имя файла базы данных? Из PerformanceTuningWindows :

Будьте ОЧЕНЬ, ОЧЕНЬ осторожны, когда вы называете свою базу данных, особенно расширение

. Например, если вы дадите всем своим базам данных расширение .sdb (База данных SQLite, хорошее имя, эй? Я так и думал, когда все равно выбираю его ...) вы обнаруживаете, что расширение SDB уже связано с ПАКЕТАМИ APPFIX.

А теперь самое интересное: APPFIX - это исполняемый файл / пакет, который распознает Windows XP, и он будет (выделено мной) ДОБАВИТЬ БАЗУ ДАННЫХ В ФУНКЦИОНАЛЬНОСТЬ ВОССТАНОВЛЕНИЯ СИСТЕМЫ

Это означает, что оставайтесь со мной здесь, каждый раз, когда вы записываете ЧТО-нибудь в базу данных, система Windows XP считает, что какой-то чертов исполняемый файл изменился, и копирует ВСЕ 800 мегабайт базы данных в каталог восстановления системы ....

Я рекомендую что-нибудь вроде DB или DAT.

2
ответ дан 3 December 2019 в 14:34
поделиться

У нас была очень похожая проблема с использованием вложенных транзакций с классом TransactionScope. Мы думали , что все действия с базой данных происходили в одном потоке ... однако мы были пойманы механизмом транзакций ... в частности, транзакцией Ambient.

По сути, была транзакция выше по цепочке, к которой, с помощью магии ado, автоматически подключилось соединение. В результате, даже если мы думали, что записываем в базу данных в одном потоке, запись не выполнялась. Это действительно происходит до тех пор, пока не будет зафиксирована самая верхняя транзакция. В этот «неопределенный» момент база данных была записана таким образом, что она была заблокирована вне нашего контроля.

Решение заключалось в том, чтобы гарантировать, что база данных sqlite не принимает непосредственного участия в внешней транзакции, используя что-то вроде:

using(TransactionScope scope = new TransactionScope(TransactionScopeOptions.RequiresNew))
{
  ...
  scope.Complete()
}
5
ответ дан 3 December 2019 в 14:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: