2008-11-15 4 views
4

Я занимаюсь улучшением производительности SQLite для своего сайта, особенно в отношении транзакций. По сути, я ищу способ отложить запись базы данных в процессе, чтобы все они могли быть выполнены сразу. Однако, когда я накапливаю запросы на обновление, я хотел бы, чтобы другие процессы могли читать и записывать в базу данных, и только блокировать файл для записи, как только коммит выдается в процессе.SQLite неэксклюзивный ЗАЩИТНЫЙ замок?

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

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

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

обновление: Что я имею в виду, когда я говорю «делать все мои обновления сразу», по существу, с использованием транзакций в SQLite только получить эксклюзивную блокировку и запись на диск один раз в процессах, а не один раз в запросе. Это приводит к 100-кратным ускорениям с использованием SQLite.

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

Я признаю, что эта проблема может быть преждевременной оптимизацией, поскольку я еще не столкнулся с какими-либо штрафами исполнения, но я выполнил несколько простых тестов и 100 пользователей, каждый из которых создает и запускает транзакцию со 100 запросами, занимает около 4 секунд в PHP на моей машине.

ответ

3

SQLite поддерживает ATTACH, чтобы прикрепить одну базу данных к другой базе данных. Возможно, вы можете накапливать свои данные в отдельной базе данных, и когда вы будете готовы объединить накопленные строки, присоедините отдельную базу данных, скопируйте строки в один оператор и отсоедините.

Редактировать: аналогичное предложение OP было сделано на mailing list thread у пользователей sqlite с последующим обсуждением.

+0

Это может сработать, но кажется уродливым взломом. Какую производительность он получает? – 2008-11-15 02:02:36

1

Лучше, чем прикрепить базу данных, просто создать временную таблицу. (CREATE TEMPORARY ...)

И взгляните на новый режим журнала WAL, который делает то, что вы пытаетесь сделать вручную, и позволяет одновременную запись и чтение (но не одновременную запись).

#pragma journal_mode = WAL

Смежные вопросы