升级django-oauth-toolkit至3.0.1后执行migrate时,0012_add_token_checksum迁移无法完成
升级django-oauth-toolkit至3.0.1后执行migrate时,0012_add_token_checksum迁移无法完成
遇到这种迁移卡住的情况,我之前帮同事排查过类似问题,大概率是下面几个原因导致的,你可以逐一排查:
最常见原因:数据库中Token记录量过大
0012_add_token_checksum这个迁移的核心操作是给所有已有的AccessToken和RefreshToken记录生成并填充checksum字段——这个字段是基于token、client_id、user_id的哈希值生成的。如果你的数据库里这两个表的记录数特别多(比如几十万甚至上百万条),这个批量计算和更新的过程会非常耗时,看起来像是卡住了,但其实后台还在处理。
解决办法:
先确认数据量:登录数据库,执行查询看看两个表的记录数:
-- MySQL/PostgreSQL通用 SELECT COUNT(*) FROM oauth2_provider_accesstoken; SELECT COUNT(*) FROM oauth2_provider_refreshtoken;如果记录数确实很大,建议先不要中断迁移,给它足够的时间(比如半小时甚至更久,取决于服务器性能)完成。
手动批量更新+标记迁移完成:如果等不及或者服务器性能实在跟不上,可以手动完成数据填充,再让Django跳过这个迁移:
- 首先停止当前卡住的migrate进程;
- 手动执行SQL批量更新(注意根据你的数据库类型调整哈希函数):
这里用-- MySQL 版本 UPDATE oauth2_provider_accesstoken SET checksum = SHA2(CONCAT(token, client_id, COALESCE(user_id, '')), 256); UPDATE oauth2_provider_refreshtoken SET checksum = SHA2(CONCAT(token, client_id, COALESCE(user_id, '')), 256); -- PostgreSQL 版本 UPDATE oauth2_provider_accesstoken SET checksum = ENCODE(SHA256(CONCAT(token, client_id, COALESCE(user_id::text, ''))::bytea), 'hex'); UPDATE oauth2_provider_refreshtoken SET checksum = ENCODE(SHA256(CONCAT(token, client_id, COALESCE(user_id::text, ''))::bytea), 'hex');COALESCE处理user_id为null的情况,避免拼接出错。 - 最后标记这个迁移已经完成,让Django不再执行它:
python manage.py migrate --fake oauth2_provider 0012_add_token_checksum
其他可能的原因
1. 数据库锁冲突
如果你的应用在迁移期间还有其他进程在访问数据库(比如生产环境没停服务就执行migrate),可能会出现锁等待的情况,导致迁移卡住。
解决办法:
- 暂时停止所有访问该数据库的应用进程;
- 登录数据库查看锁情况:
- MySQL:执行
SHOW PROCESSLIST;,找到状态为Waiting for table metadata lock或者Locked的进程,杀掉对应的PID; - PostgreSQL:执行
SELECT * FROM pg_locks WHERE NOT granted;,找到等待锁的进程,用SELECT pg_terminate_backend(pid);终止它;
- MySQL:执行
- 重新执行migrate。
2. 数据库性能不足
如果数据库服务器的CPU、内存或者磁盘IO资源不足,处理大量数据的更新操作会非常缓慢,看起来像是卡住了。
解决办法:
- 临时提升数据库服务器的资源配额(如果是云数据库的话);
- 迁移前先清理无效的Token记录(比如过期很久的Token),减少需要处理的数据量。
3. 异常数据导致计算失败
如果数据库中存在token为null的异常记录,可能会导致哈希计算失败,进而让迁移卡住。
解决办法:
- 查询是否存在异常记录:
SELECT * FROM oauth2_provider_accesstoken WHERE token IS NULL; SELECT * FROM oauth2_provider_refreshtoken WHERE token IS NULL; - 如果有这类记录,先删除或者修复它们,再重新执行migrate。
备注:内容来源于stack exchange,提问作者Augusto
相关产品推荐
相关产品推荐

