🔥

Тред (Саша Аскеров)


Хитрые моменты с 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.

Саша АскеровСаша Аскеров