SQLite неисключительная зарезервированная блокировка? - PullRequest
4 голосов
/ 15 ноября 2008

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

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

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

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

update: То, что я имею в виду, когда говорю "делать все свои обновления сразу", по сути, использует транзакции в SQLite, чтобы получить только ИСКЛЮЧИТЕЛЬНУЮ блокировку и запись на диск один раз для процессов, а не один раз для запроса , Это приводит к 100-кратному ускорению с использованием SQLite.

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

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

Ответы [ 2 ]

3 голосов
/ 15 ноября 2008

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

Редактировать: аналогичное предложение было сделано в потоке списка рассылки на sqlite-users с последующим обсуждением.

1 голос
/ 21 декабря 2010

Лучше, чем прикрепить базу данных, просто создать временную таблицу. (СОЗДАТЬ ВРЕМЕННОЕ ...)

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

# pragma journal_mode = WAL

...