备份并重建 django sqlite3数据库(migrate 失败) **引言** 在 Django 开发过程中,有时由于手动删除历史迁移文件(migrate files)或其它原因,可能导致数据库结构与模型定义不匹配,从而引发数据异常。此时,需要重建数据库并恢复数据。 **1. 备份源数据库** 首先,我们需要备份源数据库中的业务数据。 **1.1 获取表名** 使用 SQLite 命令行工具,列出源数据库中的所有表名: ```bash sqlite3 db.sqlite3 .tables ``` **1.2 排除系统表** 由于 Django 的系统表(以 `django_` 开头)和权限表 `auth_group_permissions` 可以通过迁移文件重建,因此在备份时应排除这些表。 **1.3 编写备份脚本** 创建一个 Bash 脚本,用于备份需要保留的业务数据表: ```bash #!/bin/bash # 源数据库 SOURCE_DB="db.sqlite3" # 目标数据库(备份文件) TARGET_DB="db.sqlite3.back" # 要备份的表列表 TABLES=( "account_account" "account_account_groups" "account_account_user_permissions" "album_photoes" "auth_group" "blog_blogpost" "blog_category" ) for table in "${TABLES[@]}"; do echo "Backing up $table..." sqlite3 "$SOURCE_DB" ".dump $table" | sqlite3 "$TARGET_DB" done echo "Backup completed." ``` **2. 删除原数据库并重建** 接下来,删除原数据库文件,并执行迁移命令重建数据库结构: ```bash rm db.sqlite3 python3 manage.py makemigrations python3 manage.py migrate ``` **3. 恢复数据** 此时,数据库已重建,但业务数据为空。我们需要将备份的数据恢复到新数据库中。 **3.1 编写恢复脚本** 创建一个 Bash 脚本,用于将备份数据恢复到新数据库,这里和导出脚本不同。导出使用的是`tables.dump`方法,而回写数据使用的是`insert`方法,这是因为django重新创建表的时候,字段的顺序不一定和原表一致。 ```bash #!/bin/bash # 源数据库(备份文件) SOURCE_DB="db.sqlite3.back" # 目标数据库 TARGET_DB="db.sqlite3" # 要恢复的表列表 TABLES=( "account_account" "account_account_groups" "account_account_user_permissions" "album_photoes" "blog_blogpost" "blog_category" ) for table_name in "${TABLES[@]}"; do echo "Restoring $table_name..." # 获取源表的列名 columns=$(sqlite3 "$SOURCE_DB" "PRAGMA table_info($table_name);" | awk -F'|' '{print $2}' | tr '\n' ',' | sed 's/,$//') # 生成 INSERT INTO ... SELECT ... 语句 if [ -n "$columns" ]; then # 使用 ATTACH DATABASE 命令 sqlite3 "$TARGET_DB" "ATTACH DATABASE '$SOURCE_DB' AS source_db; INSERT INTO $table_name ($columns) SELECT $columns FROM source_db.$table_name; DETACH DATABASE source_db;" else echo "Error: Failed to retrieve columns for table $table_name" fi done echo "Restore completed." ``` **3.2 执行恢复脚本** 运行恢复脚本,将备份数据导入到新数据库。 **注意事项** * 在执行任何数据库操作之前,请务必备份源数据。 * 在恢复数据时,请确保源数据库和自动建立的目标数据库的表结构(至少字段)一致,否则会插入失败。 来自 大脸猪 写于 2025-03-10 17:56 -- 更新于2025-03-10 18:34 -- 0 条评论