Я занимаюсь улучшением производительности SQLite для своего сайта, особенно в отношении транзакций. По сути, я ищу способ отложить запись в базу данных в процессе, чтобы все они могли быть выполнены одновременно. Однако, пока я накапливаю запросы на обновление, я хотел бы, чтобы другие процессы могли как читать, так и писать в базу данных, и блокировать файл для записи только после того, как в процессе выдается фиксация.
При просмотре документации кажется, что после того, как в транзакции выдается команда обновления, процесс получает ЗАБРОСОВАННУЮ блокировку, что (если я правильно помню) означает, что любой другой процесс, который пытается добавить запрос на обновление к своей собственной транзакции или зафиксировать транзакцию не может сделать это и поэтому блокируется до тех пор, пока транзакция не зафиксирует процесс с блокировкой.
Я уверен, что против этой конкретной функции есть очень веские причины для целостности данных. Все, что я могу сказать, это то, что в моем случае выполнение этих обновлений одновременно не представляет опасности.
Одно из решений состоит в том, что в каждом процессе я мог накапливать текст запросов, которые я хочу вызвать, в массиве, а затем перебирать его, как только я буду готов написать, но мне интересно, возможно ли, что транзакция SQLite может быть сделана для сделай это для меня автоматически.
Обновить: То, что я имею в виду, когда говорю «выполнение всех моих обновлений сразу», по сути, заключается в использовании транзакций в SQLite только для получения ИСКЛЮЧИТЕЛЬНОЙ блокировки и записи на диск только один раз для каждого процесса, а не один раз для каждого запроса. Это приводит к 100-кратному ускорению при использовании SQLite.
Я провел базовое тестирование, и мне кажется, что если у вас есть несколько процессов, добавляющих запросы к своим транзакциям, после того, как вы нажмете запрос на обновление, этот процесс попытается получить блокировку RESERVED. Поскольку только один процесс может иметь зарезервированную блокировку, это означает, что любые другие процессы, пытающиеся получить блокировку, будут блокироваться до тех пор, пока процесс с блокировкой не завершит транзакцию.
Я признаю, что эта проблема может быть преждевременной оптимизацией, поскольку я еще не столкнулся с какими-либо штрафами за производительность, но я провел несколько простых тестов, и каждый из 100 пользователей, создающих и выполняющих транзакцию со 100 запросами, занимает около 4 секунд в PHP на моей машине.





SQLite поддерживает ПРИКРЕПЛЯТЬ для присоединения одной базы данных к другой базе данных. Возможно, вы сможете накапливать данные в отдельной базе данных, а когда будете готовы объединить накопленные строки, присоединить отдельную базу данных, скопировать строки в одном операторе и отсоединить.
Обновлено: аналогичное предложение для OP было сделано на ветка списка рассылки у пользователей sqlite с некоторым последующим обсуждением.
Производительность может быть отличной, поскольку транзакции в каждой базе данных, пока они не подключены, не могут мешать друг другу. Это особенно эффективно, когда данные накапливаются в базе данных: memory:, к которой вы присоединяете основную базу данных.
Лучше, чем присоединять базу данных, - это просто создать временную таблицу. (СОЗДАТЬ ВРЕМЕННОЕ ...)
И взгляните на новый режим журнала WAL, который делает именно то, что вы пытаетесь сделать вручную, и позволяет одновременную запись и чтение (хотя и не одновременную запись).
#pragma journal_mode = WAL
Это может сработать, но похоже на уродливую уловку. Какая у него производительность?