64 lines
2.0 KiB
Markdown
64 lines
2.0 KiB
Markdown
|
# Database migrations
|
||
|
|
||
|
This app ships with a lightweight SQL migration system to safely upgrade a running site when code changes require database changes.
|
||
|
|
||
|
## Concepts
|
||
|
|
||
|
- Migrations live in `doc/database/migrations/` and are plain `.sql` files.
|
||
|
- They are named in a sortable order, e.g. `YYYYMMDD_HHMMSS_description.sql`.
|
||
|
- Applied migrations are tracked in a DB table called `migrations`.
|
||
|
- Use the CLI script `scripts/migrate.php` to inspect and apply migrations.
|
||
|
|
||
|
## Usage
|
||
|
|
||
|
1. Show current status
|
||
|
|
||
|
```bash
|
||
|
php scripts/migrate.php status
|
||
|
```
|
||
|
|
||
|
2. Apply all pending migrations
|
||
|
|
||
|
```bash
|
||
|
php scripts/migrate.php up
|
||
|
```
|
||
|
|
||
|
3. Typical deployment steps
|
||
|
|
||
|
- Pull new code from git.
|
||
|
- Put the site in maintenance mode (optional, recommended for sensitive changes).
|
||
|
- Run `php scripts/migrate.php status`.
|
||
|
- If there are pending migrations, run `php scripts/migrate.php up`.
|
||
|
- Clear opcache if applicable and resume traffic.
|
||
|
|
||
|
## Authoring new migrations
|
||
|
|
||
|
1. Create a new SQL file in `doc/database/migrations/`, e.g.:
|
||
|
|
||
|
```
|
||
|
doc/database/migrations/20250924_170001_add_user_meta_theme.sql
|
||
|
```
|
||
|
|
||
|
2. Write forward-only SQL. Avoid destructive changes unless absolutely necessary.
|
||
|
|
||
|
3. Prefer idempotent SQL. For MySQL 8.0+ you can use `ADD COLUMN IF NOT EXISTS`. For older MySQL/MariaDB versions, either:
|
||
|
|
||
|
- Check existence in PHP and conditionally run DDL, or
|
||
|
- Write migrations that are safe to run once and tracked by the `migrations` table.
|
||
|
|
||
|
## Notes
|
||
|
|
||
|
- The application checks for pending migrations at runtime and shows a warning banner but will not auto-apply changes.
|
||
|
- The `migrations` table is created automatically by the runner if missing.
|
||
|
- The runner executes each migration inside a single transaction (when supported by the storage engine for the statements used). If any statement fails, the migration batch is rolled back and no migration is marked as applied.
|
||
|
|
||
|
## Example migration
|
||
|
|
||
|
This repo includes an example migration that adds a per-user theme column:
|
||
|
|
||
|
```
|
||
|
20250924_170001_add_user_meta_theme.sql
|
||
|
```
|
||
|
|
||
|
It adds `user_meta.theme` used to store each user's preferred theme.
|