RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Small. Fast. Reliable.
Choose any three.

SQLite по сети: проблемы и соображения

Введение

Пользователи библиотеки SQLite, особенно разработчики приложений, которые хотят получить доступ к базе данных SQLite от различных систем, связанных сетью, часто испытывают желание просто открыть соединение с базой данных, определяя имя файла, которое ссылается на файл базы данных где-нибудь в сетевой файловой системе ("удаленная база данных"). К этому "файлу" тогда получают доступ посредством OS API, которые разрешают иллюзию I/O из/в местный файл. Иллюзия хороша, но несовершенна важными способами.

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

Проблемы, возникающие с удаленными файлами базы данных

Эта диаграмма показывает компоненты и их связи для справки в следующем обсуждении:

Client Application SQLite Database Engine Database File(s) SQLiteб═API Calls DBб═Engine Fileб═I/O

Проблемы являются результатом свойств и использования двух каналов данных/контроля между вышеупомянутыми тремя блоками.

Объем канального трафика

Канал "API Call" несет меньше информации, чем канал "File I/O". Вызовы API, чтобы представить запросы или определить модификацию данных, обычно требуют, чтобы существенно меньше битов было передано, чем передается файлу базы данных, чтобы сохранить или найти данные. Поиск результата запроса будет обычно требовать намного большего количества трафика, чем API, потому что данные, которые будут возвращены, должны редко находиться, не читая лишние данные.

Ширина канала

Канал API Call работает на скоростях оперативной памяти процессора (Giga-words/second) с данными, часто передаваемыми ссылкой (которые не копируются). Напротив, даже самые быстрые каналы файлового ввода-вывода медленнее. Они требуют, чтобы данные были скопированы, обычно по преобразованию в последовательную форму.

Когда канал файлового ввода-вывода включает сетевое соединение (в дополнение к некоторому подлинному файловому вводу-выводу в его дальнем конце), дополнительная медлительность неизбежно наложена. Даже там, где сырая скорость передачи не ограничивает пропускную способность, трафик должен все еще быть пакетирован и буферизован на обоих концах. Дополнительные слои обработчиков I/O добавляют задержки планирования. Однако, замедленные передачи это не значащая проблема с сетевыми файловыми системами.

Надежность канала

Канал "API Call" очень надежен, до такой степени, что коэффициенты ошибок не установлены и проигнорированы как незначительные. Канал терпит неудачу только, когда система теряет питание.

Канал "File I/O", когда это непосредственно достигает местного устройства хранения данных, также очень надежен. У локальных устройств также есть особенность, которая очень важна для предоставления возможности программного обеспечения управления базой данных, чтобы гарантировать поведение ACID: когда все процессы записи устройству закончили работу (когда POSIX POSIX fsync() или Windows FlushFileBuffers() завершились), файловая система тогда или хранит "записанные" данные, или сделает это прежде, чем хранить любые впоследствии записанные данные.

Когда аппарат сетевой файловой системы и программные слои вставляются между клиентами файловой системы и файловой системой, значительные источники неудачи вводятся. В то время, как сетевые передачи данных проверяются на ошибки хорошо, пакеты передачи не все достоверно прибывают к своему месту назначения. При условии столкновения пакетов повторения могут наложить превышение задержек, что необходимо для подобных данных, чтобы достигнуть места хранения. А это приводит к проблемам при записи, включая тайм-ауты.

Из-за разупорядочивания и прямой потери данных, которые происходят в сетевой файловой системе, очень важно, чтобы запись в файл ТОЧНО была сделана на момент начала следующей записи в файл. Эта гарантия получена при помощи разработанных и правильно осуществленных функций OS fsync() (или аналог). К сожалению для некоторых ситуаций операция по синхронизации сетевой файловой системы может быть менее прочной, чем синхронизация локальной файловой системы. Достижение прочной синхронизации перед лицом сетевых ошибок транспортировки пакета трудно, и гарантии иногда смягчаются в пользу скорости работы.

Подобная опасность возникает с блокировкой файла в сетевых файловых системах. SQLite полагается на монопольные блокировки для операций записи, а те, как было известно, действовали неправильно для некоторых сетевых файловых систем. Это привело к повреждению базы данных. Это может произойти снова.

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

Работа и проблемы надежности

Из вышеупомянутой диаграммы и обсуждения, очевидно, что работа ухудшается вставкой сетевого соединения в один из этих двух каналов. Рассмотрение относительных объемов трафика между каналами API Call и File I/O показывает, что такая вставка окажет меньше влияния в канале API Call.

Рассмотрение воздействия надежности легче с более ясным результатом: вставка сетевого соединения в канал API Call может также время от времени приводить к неудачам. Но если клиентское приложение потрудилось использовать транзакции SQL/SQLite правильно, такие неудачи заставят только транзакцию терпеть неудачу и откатываться до прежнего уровня, не ставя под угрозу целостность данных. Напротив, если сетевое соединение вставляется в канал File I/O, транзакции могут потерпеть неудачу (как для вставки в API Call), но с дополнительным эффектом, что удаленная база данных испорчена.

Эти сетевые проблемы ненадежности могут быть смягчены, полностью или до приемлемой степени, при помощи SQLite в режиме rollback. Однако, библиотека SQLite не проверена в сценариях работы через сеть. Следовательно, использование удаленной базы данных сделано на риск пользователя.

Рекомендации

Обычно, если ваши данные отделены от применения сетью, вы хотите использовать базу данных клиент-сервер. Это вследствие того, что ядро базы данных действует как уменьшающий пропускную способность фильтр на трафике базы данных.

Если ваши данные отделены от применения сетью, вы хотите, чтобы связь низкого трафика была по сети, но не связь с интенсивным трафиком. Это означает, что ядро базы данных должно быть на той же самой машине, как сама база данных. Такое имеет место с базой данных клиент-сервер как PostgreSQL. SQLite отличается в том, что ядро базы данных работает на той же самой машине, как приложение, которое вынуждает связь более высокого трафика использовать сеть в сценариях удаленной базы данных. Это обычно приводит к более низкой производительности.

Сетевые файловые системы не поддерживают способность сделать одновременное чтение и запись, в то же время сохраняя базу данных последовательной. Таким образом, если у вас есть многократные клиенты на многократных различных машинах, которые должны сделать одновременно чтение и запись БД, у вас есть этот выбор:

1. Используйте ядро базы данных клиент-сервер. PostgreSQL отличный выбор.

2. Переведите базу данных SQLite в режим WAL, но сделайте все чтения и записи от процессов на той же самой машине, которая хранит файл базы данных. Осуществите прокси на машине баз данных, который выполняет чтение и запись от других машин.

3. Используйте SQLite в режиме rollback. Это означает, что у вас могут быть многократные одновременные читатели или один писатель, но не одновременные читатели и писатели.

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

Итог

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