3.7 KiB
SQlite
Purpose
This sqlite
package provides a basic interface for interacting with the
embedded sqlite database used by various InfluxDB services which require storing
relational data.
The actual sqlite driver is provided by
mattn/go-sqlite3
.
Usage
A single instance of SqlStore
should be created using the NewSqlStore
function. Currently, this is done in the top-level launcher
package, and a
pointer to the SqlStore
instance is passed to services which require it as
part of their initialization.
The jmoiron/sqlx
package provides a
convenient and lightweight means to write and read structs into and out of the
database and is sufficient for performing simple, static queries. For more
complicated & dynamically constructed queries, the
Masterminds/squirrel
package can be
used as a query builder.
Concurrent Access
An interesting aspect of using the file-based sqlite database is that while it can support multiple concurrent read requests, only a single write request can be processed at a time. A traditional RDBMS would manage concurrent write requests on the database server, but for this sqlite implementation write requests need to be managed in the application code.
In practice, this means that code intended to mutate the database needs to obtain a write lock prior to making queries that would result in a change to the data. If locks are not obtained in the application code, it is possible that errors will be encountered if concurrent write requests hit the database file at the same time.
Migrations
A simple migration system is implemented in migrator.go
. When starting the
influx daemon, the migrator runs migrations defined in .sql
files using
sqlite-compatible sql scripts. Records of these migrations are maintained in a
table called "migrations". If records of migrations exist in the "migrations"
table that are not embedded in the binary, an error will be raised on startup.
When creating new migrations, follow the file naming convention established by
existing migration scripts, which should look like 00XX_script_name.up.sql
&
00xx_script_name.down.sql
for the "up" and "down" migration, where XX
is the
version number. New scripts should have the version number incremented by 1.
The "up" migrations are run when starting the influx daemon and when metadata
backups are restored. The "down" migrations are run with the influxd downgrade
command.
In-Memory Database
When running influxd
with the --store=memory
flag, the database will be
opened using the :memory:
path, and the maximum number of open database
connections is set to 1. Because of the way in-memory databases work with
sqlite, each connection would see a completely new database, so using only a
single connection will ensure that requests to influxd
will return a
consistent set of data.
Backup & Restore
Methods for backing up and restoring the sqlite database are available on the
SqlStore
struct. These operations make use of the sqlite backup
API made available by the go-sqlite3
driver. It is possible to restore and backup into sqlite databases either stored
in memory or on disk.
Sqlite Features / Extensions
There are many additional features and extensions available, see the go-sqlite3 package docs for the full list.
We currently use the sqlite_foreign_keys
and sqlite_json
extensions for
foreign key support & JSON query support. These features are enabled using
build tags defined in the Makefile
and .goreleaser
config for use in
local builds & CI builds respectively.