[SQLite] Использование в многопоточном RPC-сервере
От: acDev Россия  
Дата: 05.10.13 13:46
Оценка:
Начал писать RPC-сервер, который клиентские запросы обрабатывает через пул потоков.
Все данные клиентов решено хранить во встраиваемой БД SQLite. Целевая платформа пока что только Windows.

На офф. сайте как то неоднозначно описаны варианты многопоточного применения SQLite: http://www.sqlite.org/threadsafe.html
На хабре более "понятливое" описание режимов:

1) Serialized (надо указать флаг SQLITE_OPEN_FULLMUTEX при открытии соединения). В этом режиме потоки могут как угодно дергать вызовы SQLite, никаких ограничений. Но все вызовы блокируют друг друга и обрабатываются строго последовательно.
2) Multi-thread (SQLITE_OPEN_NOMUTEX). В этом режиме нельзя использовать одно и то же соединение одновременно из нескольких потоков (но допускается одновременное использование разных соединений разными потоками). Обычно используется именно этот режим.


В самих исходниках sqlite за режим многопоточности отвечает макрос SQLITE_THREADSAFE. Значения его таковы:
0 = однопоточный вариант использования sqlite
1 = Serialized режим
2 = Multi-thread режим

Часть кода sqlite:
    case SQLITE_CONFIG_SINGLETHREAD: {
      /* Disable all mutexing */
      sqlite3GlobalConfig.bCoreMutex = 0;
      sqlite3GlobalConfig.bFullMutex = 0;
      break;
    }
    case SQLITE_CONFIG_SERIALIZED: {
      /* Enable all mutexing */
      sqlite3GlobalConfig.bCoreMutex = 1;
      sqlite3GlobalConfig.bFullMutex = 1;
      break;
    }
    case SQLITE_CONFIG_MULTITHREAD: {
      /* Disable mutexing of database connections */
      /* Enable mutexing of core data structures */
      sqlite3GlobalConfig.bCoreMutex = 1;
      sqlite3GlobalConfig.bFullMutex = 0;
      break;
    }


По исходному коду так же видно, что при bFullMutex = 1 абсолютно все функции sqlite (open,prepare,...,close) выполняются внутри критической секции (на винде).

Теперь расскажу как я представляю себе эти режимы работы:
1) Serialized — После получения описателя Х базы данных А (вызов sqlite3_open) в основном потоке, полученный описатель Х можно свободно использовать в других потоках не запариваясь на сихронизацию доступа.
2) Multi-thread — Получать описатель Х базы данных А (вызов sqlite3_open) следует в каждом потоке (или клиентской сессии). Всю сихронизацию доступа к файлу базы данных выполняет sqlite, но возможно получение статуса SQLITE_BUSY, что свидетельствует о занятости БД.

Мои представления о многопоточных режимах sqlite верны?
Re: [SQLite] Использование в многопоточном RPC-сервере
От: wildwind Россия  
Дата: 05.10.13 14:11
Оценка: 4 (1)
Здравствуйте, acDev, Вы писали:

D>Начал писать RPC-сервер, который клиентские запросы обрабатывает через пул потоков.

D>Все данные клиентов решено хранить во встраиваемой БД SQLite. Целевая платформа пока что только Windows.

Безотносительно к режиму работы нужно понимать, что все блокировки в SQLite — табличные. То есть если все потоки будут что-то писать в одну и ту же таблицу (например лог запросов), это будет точкой сериализации, независимо от режима. Если вы хотите распараллелить не только обработку, но и запись, SQLite не подойдет.
Re[2]: [SQLite] Использование в многопоточном RPC-сервере
От: acDev Россия  
Дата: 05.10.13 17:00
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Безотносительно к режиму работы нужно понимать, что все блокировки в SQLite — табличные. То есть если все потоки будут что-то писать в одну и ту же таблицу (например лог запросов), это будет точкой сериализации, независимо от режима. Если вы хотите распараллелить не только обработку, но и запись, SQLite не подойдет.


В требованиях указано, что желательно использовать встраиваемую БД. Да и клиентов будет не более 3-х десятков.
При разработке буду использовать либо Serialized, либо Multi-Thread режим. А когда будет готов какойто рабочий прототип, то может быть переведу в режим WAL.
Вот что пишут на хабре о WAL-режиме:

В режиме WAL (Write-Ahead Logging) «читатели» БД и «писатели» в БД уже не мешают друг другу, то есть допускается модификация данных при одновременном чтении. Короче говоря, это шаг в сторону больших и серьезных СУБД, в которых все так и есть. Утверждается также, что SQLite в WAL работает быстрее.

Фактически, в режиме WAL данные БД разделяются между БД и файлом журнала. Операция checkpoint переносит данные в БД. По умолчанию, это делается автоматически, если журнал занял 1000 страниц БД.
То есть, идут быстрые COMMIT-ы и вдруг какой-то COMMIT задумался и начал делать checkpoint. Если такое поведение нежелательно, можно делать checkpoint вручную (когда все спокойно), можно это делать и в отдельном процессе.

Re: [SQLite] Использование в многопоточном RPC-сервере
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.10.13 17:55
Оценка:
Здравствуйте, acDev, Вы писали:

D>Начал писать RPC-сервер, который клиентские запросы обрабатывает через пул потоков.

D>Все данные клиентов решено хранить во встраиваемой БД SQLite. Целевая платформа пока что только Windows.

Наш опыт работы с SQLite в сервере достаточно негативный. При более-менее высокой нагрузке он начинает бросать всякие хаотические вещи типа "Database is locked". При этом в отличие от настоящих СУБД средств оттрассировать происходящее в нём я не вижу.

Избавиться от Database is locked удалось только вручную расставив примитивы синхронизации — скорость получилась так себе, но он хотя бы работает.
В общем, осталось впечатление, что для серверной работы SQLite надо уметь готовить. Просто "воткнуть и поехать" можно только для случаев, когда параллельной работы с базой заведомо не будет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: [SQLite] Использование в многопоточном RPC-сервере
От: Plague Россия 177230800
Дата: 07.10.13 10:24
Оценка:
Здравствуйте, acDev, Вы писали:

D>В требованиях указано, что желательно использовать встраиваемую БД.


Что думаете про FirebirdSQL ?
Re[3]: [SQLite] Использование в многопоточном RPC-сервере
От: wildwind Россия  
Дата: 07.10.13 23:54
Оценка:
Здравствуйте, acDev, Вы писали:

D>Вот что пишут на хабре о WAL-режиме:


Пишут верно. Я же писал о другом сценарии, о параллельной записи, а не записи + чтении.
Re[4]: [SQLite] Использование в многопоточном RPC-сервере
От: acDev Россия  
Дата: 08.10.13 06:30
Оценка:
Здравствуйте, wildwind, Вы писали:

D>>Вот что пишут на хабре о WAL-режиме:


W>Пишут верно. Я же писал о другом сценарии, о параллельной записи, а не записи + чтении.


Моё мнение, что абсолютно параллельной записи не бывает.
Я считаю, что параллельная запись в современных СУБД осуществляется одним из след. способов:
1) блокировка всех объектов БД
2) блокировка записи в конкретную таблицу (или таблицы)
3) блокировка записи в конкретную станицу файла БД (или несколько страниц)
4) блокировка записи в конкретную строку таблицы

ЗЫ. В чудеса не верю ))
Re[5]: [SQLite] Использование в многопоточном RPC-сервере
От: wildwind Россия  
Дата: 08.10.13 07:23
Оценка:
Здравствуйте, acDev, Вы писали:

D>ЗЫ. В чудеса не верю ))


Это все к чему, я не понял. Ты на что-то возражаешь? Вроде не на что.
Re[6]: [SQLite] Использование в многопоточном RPC-сервере
От: acDev Россия  
Дата: 08.10.13 07:47
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Безотносительно к режиму работы нужно понимать, что все блокировки в SQLite — табличные. То есть если все потоки будут что-то писать в одну и ту же таблицу (например лог запросов), это будет точкой сериализации, независимо от режима. Если вы хотите распараллелить не только обработку, но и запись, SQLite не подойдет.


При большом количестве одновременных клиентских запросов (более 100 за секунду) SQLite конечно не подойдёт.
Но по моему ТЗ я ну никак не вижу такой нагрузки на сервак. Максимум прогнозирую 3 запроса за секунду. Поэтому и делаю сейчаз на основе SQLite.

А вообще вопрос изначально был о правильности моих представлений о правильном использовании SQLite в многопоточной серверной среде.
Re[7]: [SQLite] Использование в многопоточном RPC-сервере
От: wildwind Россия  
Дата: 08.10.13 09:14
Оценка:
Здравствуйте, acDev, Вы писали:

D>При большом количестве одновременных клиентских запросов (более 100 за секунду) SQLite конечно не подойдёт.

D>Но по моему ТЗ я ну никак не вижу такой нагрузки на сервак. Максимум прогнозирую 3 запроса за секунду. Поэтому и делаю сейчаз на основе SQLite.

Мы как будто каждый о своем говорим. Я разве что-то писал об общем количестве запросов? При желании, думаю можно и 500 выжать, при определенных условиях. Однако, при трех запросах в секунду, и та проблема, о которой писал я, полагаю будет не актуальна.

D>А вообще вопрос изначально был о правильности моих представлений о правильном использовании SQLite в многопоточной серверной среде.


На основной вопрос я и не пытался отвечать.
Re[2]: [SQLite] Использование в многопоточном RPC-сервере
От: PPA Россия http://flylinkdc.blogspot.com/
Дата: 16.10.13 10:08
Оценка:
Здравствуйте, Sinclair, Вы писали:
S>Наш опыт работы с SQLite в сервере достаточно негативный. При более-менее высокой нагрузке он начинает бросать всякие хаотические вещи типа "Database is locked". При этом в отличие от настоящих СУБД средств оттрассировать происходящее в нём я не вижу.

Для реакции на таймаут можно использовать sqlite3_busy_handler
для трассировки есть sqlite3_trace не пробовали?
Re[3]: [SQLite] Использование в многопоточном RPC-сервере
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.10.13 07:31
Оценка:
Здравствуйте, PPA, Вы писали:

PPA>Для реакции на таймаут можно использовать sqlite3_busy_handler

PPA>для трассировки есть sqlite3_trace не пробовали?

Нет, не пробовали — по незнанию. Но бегло почитав его описание, я не могу понять, как мне анализировать стейтменты:
— как получить реальный план запроса с оценками стоимости каждого из этапов
— как трассировать графы ожидания, чтобы понять, на каких ресурсах блокировки простаивают максимальное время

Может, есть какая-то книга или блог "оптимизация производительности sqlite для чайников"?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: [SQLite] Использование в многопоточном RPC-сервере
От: wildwind Россия  
Дата: 18.10.13 18:45
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>- как получить реальный план запроса с оценками стоимости каждого из этапов

S>- как трассировать графы ожидания, чтобы понять, на каких ресурсах блокировки простаивают максимальное время

Не нужно предъявлять в sqlite те же требования, что и к "большой тройке". Они совсем в разных весовых категориях.
Re: [SQLite] Использование в многопоточном RPC-сервере
От: PM  
Дата: 19.10.13 06:18
Оценка: 62 (1)
Здравствуйте, acDev, Вы писали:

D>Начал писать RPC-сервер, который клиентские запросы обрабатывает через пул потоков.

D>Все данные клиентов решено хранить во встраиваемой БД SQLite. Целевая платформа пока что только Windows.
[дальнейшее описание пропущено]

Я уже несколько месяцев приглядываюсь к LMDB в качестве key-value store. Его автор, Howard Chu между делом сделал
sqlightning — порт SQLite со своим движком хранения данных на LMDB.

Вообще, Howard Chu высказывался не очень положительно о реализации SQLite (как впрочем и о LevelDB). По своему опыту использования SQLite я думаю что у него есть на то основания. Включение WAL, увеличение кэша для данных и эксперименты с размером страницы данных, не дали грандиозного прироста скорости доступа к данным в моей задаче (однопоточное добавление новых записей с последующим их чтением).
Re[5]: [SQLite] Использование в многопоточном RPC-сервере
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.13 06:50
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Не нужно предъявлять в sqlite те же требования, что и к "большой тройке". Они совсем в разных весовых категориях.

Ну, вот собственно именно это я и хотел донести до топик-стартера.
Именно такие неочевидные соображения могут оказаться неприятным сюрпризом для тех, кому sqlite кажется реальной альтернативой большой тройке в сервер-сайд сценариях.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.