eagleye

针对“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. 直接查询数据库系统表

MySQLSELECT table_name FROM information_schema.tables WHERE table_schema='your_db_name';

查看表名是否为全小写(users_security_eventvsUsers_Security_Event)。

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的完整代码上下文(包含外层函数/视图)

通过底层数据流向追踪,可精准定位“写入成功但无记录”的根本原因。

 

posted on 2025-07-22 21:40  GoGrid  阅读(6)  评论(0)    收藏  举报

导航