针对“SecurityEvent写入成功但数据库无记录”的深度排查方案
针对“SecurityEvent写入成功但数据库无记录”的深度排查方案
一、事务回滚:代码逻辑中的“隐形杀手”
核心怀疑:即使create_event返回对象,若其外层存在未提交的事务或异常回滚,数据会被静默撤销。
验证步骤:
1. 添加事务日志:在create_event方法中打印事务状态:
from django.db import transaction
print(f"事务状态: {'活跃' if transaction.get_connection().in_atomic_block else '非活跃'}")
若输出“活跃”,说明当前操作处于外层事务中,需检查调用create_event的视图/函数是否被@transaction.atomic装饰,或是否存在异常导致回滚。
2. 强制提交测试:在create_event中添加强制提交(仅测试用,生产环境慎用):
transaction.get_connection().commit() # 强制提交当前事务
若数据成功写入,证明外层事务未正常提交。
二、数据库路由:数据写入了“错误的库”
核心怀疑:若项目配置了数据库路由(DATABASE_ROUTERS),app_label='audit_logs'可能导致模型被路由到非默认数据库,而您查询的是默认库。
验证步骤:
1. 检查数据库路由配置:在settings.py中查找:
DATABASE_ROUTERS = ['myapp.routers.AuditLogRouter'] # 若存在此类配置
路由逻辑可能将audit_logs应用的模型定向到其他数据库(如audit_db),需查询对应数据库的users_security_event表。
2. 显式指定数据库:在查询时指定数据库别名:
# 假设路由将模型定向到 'audit_db'
SecurityEvent.objects.using('audit_db').filter(username='天天吞吞吐吐').exists()
三、表名大小写与数据库引擎冲突
核心怀疑:模型定义db_table='users_security_event',但数据库实际表名可能因引擎特性而不同(如PostgreSQL区分大小写,MySQL在Windows下不区分)。
验证步骤:
1. 直接查询数据库系统表:
o MySQL:SELECT table_name FROM information_schema.tables WHERE table_schema='your_db_name';
查看表名是否为全小写(users_security_eventvsUsers_Security_Event)。
o PostgreSQL:\dt # 列出所有表,注意大小写是否匹配
2. 修改表名测试:临时将db_table改为全小写(如users_security_event_lower),执行迁移后再次创建事件,检查新表是否有数据。
四、Django ORM缓存与数据库连接池问题
核心怀疑:连接池复用旧连接导致数据未实时刷新,或ORM查询缓存未命中最新数据。
验证步骤:
1. 直接执行原生SQL:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM users_security_event WHERE username='天天吞吞吐吐'")
print(cursor.fetchall()) # 查看是否有结果
若原生SQL能查询到数据,说明ORM查询可能被缓存,可通过SecurityEvent.objects.all().none()清除缓存。
2. 重启数据库连接:在create_event后关闭并重新打开连接:
connection.close() # 关闭当前连接
五、终极验证:数据库抓包
若以上步骤均无法定位问题,需通过数据库抓包确认Django是否真的发送了INSERT请求:
- MySQL:开启general log:SET GLOBAL general_log = 'ON';
SET GLOBAL log_output = 'TABLE'; # 日志写入mysql.general_log表
创建事件后查询日志表:SELECT event_time, argument FROM mysql.general_log WHERE argument LIKE '%INSERT INTO users_security_event%';
若存在对应INSERT语句且无错误,证明数据已写入,问题可能出在查询环节(如路由、权限);若无INSERT语句,证明ORM未执行写入(如事务未提交)。
结论与优先行动项
1. 最高优先级:检查外层事务是否回滚(添加事务状态日志)。
2. 次高优先级:确认数据库路由和表名大小写是否匹配。
3. 快速验证:执行原生SQL查询和数据库抓包,直接定位数据流向。
若完成以上步骤仍未解决,需提供:
- Django日志中audit_logs的ERROR级别输出
- 数据库general log中的INSERT语句记录
- 调用create_event的完整代码上下文(包含外层函数/视图)
通过底层数据流向追踪,可精准定位“写入成功但无记录”的根本原因。