Хитрые моменты с SqlCipher.
Очень специфичная мало кому нужная тема. Как раз для вечера субботы.
Если ваш апп с лютыми секюрити требованиями и какой-то работой с локальными данными, то вы скорее всего в курсе про SqlCipher
github.com/sqlcipher/andr…
В нем все хорошо. И всего-то надо заменить android.database.sqlite.* на net.sqlcipher.database.* и все должно заработать. И заработает. Но несколько по другому.
Все дело в том, что все что лежит в net.sqlcipher.database это форк какой-то очень древней android версии этих классов. И самое неприятное, что там есть, это по умолчанию включенный лок на все операции.
Это может оказаться критичным, если есть какие-то крупные транзакции. Тогда запрос на чтение, например для показа контента пользователю, может быть заблокирован такой транзакцией.
Лок на операции регулируется методом setLockingEnabled. В андроидном SQLiteDatabase этот метод deprecated уже много лет и ничего не делает, а SQLiteDatabase сам заботится об оптимальных блокировках.
А вот в sqlcipher он используется и по умолчанию включен. Нужно отключить, но не просто так.
Во первых включаем WAL. Что это такое есть в документации sqlite.org/wal.html Но главное, что он позволяет операциям записи и транзакциям не блокировать чтение. А операциям чтения — запись.
Во вторых, позаботимся о том, чтобы не писать в базу конкурентно. Заботится нужно только об update, insert, delete, так как транзакции идут через форсированный лок и метод setLockingEnabled на них не действует.
Как именно?
Например выделить на запись в базу отдельный single thread executor и пустить все через него.
Или сделать все записи через транзакции. Да, оверхед, но не очень большой.
Как лучше сделать зависит от конкретной ситуации и способа работы с sqlite. Мы прячем эту сложность в собственный велосипед для sqlite. Изначально он был не для этого, но и тут пригодился.
SqlCipher поддерживает Room. Им никогда не пользовался, так что про него ничего сказать не могу. Но я думаю, что там та же история, так как SQLiteDatabase просто реализует SupportSQLiteDatabase.
Саша Аскеров