Я не вижу большой нагрузки, которой Вы требуете от проверки входящего дюйм/с Наоборот, я сделал проект для одного из моих клиентов, который анализирует журналы доступа HTTP каждые пять минут (это, возможно, было в реальном времени, но он не хотел это по некоторым причинам, что я никогда полностью понял), и создает правила брандмауэра заблокировать соединения от любых IP-адресов, которые генерируют чрезмерное количество запросов, если адрес не может быть подтвержден как принадлежащий законной поисковой системе (Google, Yahoo, и т.д.).
Этот клиент выполняет услугу веб-хостинга и запускает это приложение на трех серверах, которые обрабатывают в общей сложности 800-900 доменов. Пиковое действие находится в диапазоне thousand-hits-per-second и никогда не было проблемы производительности - брандмауэры очень эффективны при отбрасывании пакетов от помещенных в черный список адресов.
И, да, технология DDOS определенно существует, который победил бы эту схему, но он не видит, что происходят в реальном мире. Наоборот, он говорит, что это значительно уменьшило нагрузку на его серверы.
Запустите Sysinternals Process Monitor и отфильтруйте имя файла при запуске вашей программы, чтобы исключить, делает ли какой-либо другой процесс что-либо с ним, и посмотреть, что именно ваша программа делает с файл. Длинный выстрел, но может дать ключ к разгадке.
На что следует обратить внимание:
не используйте соединения между несколькими потоками / процессами.
Я видел, как это происходило, когда антивирусный сканер обнаруживал изменения в файле и пытался сканировать это. Это заблокирует файл на короткий промежуток времени и вызовет хаос.
Является ли ваш файл базы данных на том же компьютере, что и приложение, или он хранится на сервере?
Вы должны создавать новое соединение в каждом потоке. Я бы упростил создание соединения, использовал везде: connection = new SQLiteConnection (connString.ToString ());
и использовал файл базы данных на том же компьютере, что и приложение, и снова протестировал.
Почему используются два разных способа создания соединения?
У этих парней были похожие проблемы (в основном, похоже, с заблокированным файлом журнала, возможно, взаимодействия TortoiseSVN ... проверьте статьи, на которые есть ссылки).
Они предложили набор рекомендаций (правильные каталоги, изменение типов ведения журнала с удаления на сохранение и т. Д.). http://sqlite.phxsoftware.com/forums/p/689/5445.aspx#5445
Параметры режима журнала обсуждаются здесь: http://www.sqlite.org/pragma. html . Вы можете попробовать TRUNCATE.
Есть ли трассировка стека во время исключения в SQL Lite?
Вы указываете, что вы «пакетируете мои коммиты с разумным интервалом». Какой интервал?
Похоже, вам не удалось связать команду с созданной вами транзакцией. . Вместо:
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 для сохранения неполного состояния транзакции.
Я бы всегда использовал соединение, транзакцию и команду в предложении using
. В первом листинге кода вы это сделали, а в третьем (создание таблиц) - нет. Я предлагаю вам сделать это тоже, потому что (кто знает?), Возможно, команды, которые создают таблицу, каким-то образом продолжают блокировать файл. Дальний выстрел ... но стоит ли выстрел?
У вас запущен Google Desktop Search (или другой индексатор файлов)? Как упоминалось ранее, Sysinternals Process Monitor может помочь вам отследить его.
Кроме того, каково имя файла базы данных? Из PerformanceTuningWindows :
Будьте ОЧЕНЬ, ОЧЕНЬ осторожны, когда вы называете свою базу данных, особенно расширение
. Например, если вы дадите всем своим базам данных расширение .sdb (База данных SQLite, хорошее имя, эй? Я так и думал, когда все равно выбираю его ...) вы обнаруживаете, что расширение SDB уже связано с ПАКЕТАМИ APPFIX.
А теперь самое интересное: APPFIX - это исполняемый файл / пакет, который распознает Windows XP, и он будет (выделено мной) ДОБАВИТЬ БАЗУ ДАННЫХ В ФУНКЦИОНАЛЬНОСТЬ ВОССТАНОВЛЕНИЯ СИСТЕМЫ
Это означает, что оставайтесь со мной здесь, каждый раз, когда вы записываете ЧТО-нибудь в базу данных, система Windows XP считает, что какой-то чертов исполняемый файл изменился, и копирует ВСЕ 800 мегабайт базы данных в каталог восстановления системы ....
Я рекомендую что-нибудь вроде DB или DAT.
У нас была очень похожая проблема с использованием вложенных транзакций с классом TransactionScope. Мы думали , что все действия с базой данных происходили в одном потоке ... однако мы были пойманы механизмом транзакций ... в частности, транзакцией Ambient.
По сути, была транзакция выше по цепочке, к которой, с помощью магии ado, автоматически подключилось соединение. В результате, даже если мы думали, что записываем в базу данных в одном потоке, запись не выполнялась. Это действительно происходит до тех пор, пока не будет зафиксирована самая верхняя транзакция. В этот «неопределенный» момент база данных была записана таким образом, что она была заблокирована вне нашего контроля.
Решение заключалось в том, чтобы гарантировать, что база данных sqlite не принимает непосредственного участия в внешней транзакции, используя что-то вроде:
using(TransactionScope scope = new TransactionScope(TransactionScopeOptions.RequiresNew))
{
...
scope.Complete()
}