• 请不要在回答技术问题时复制粘贴 AI 生成的内容
taloricag
V2EX  ›  程序员

操作记录精细到字段级别,有比较干净的方案么?

  •  
  •   taloricag · Nov 27, 2021 · 3727 views
    This topic created in 1648 days ago, the information mentioned may be changed or developed.
    就是 post 请求,需要知道修改到数据库改了什么字段做操作记录
    实际上现在操作记录的实现已经是 AOP ,在路由层丢给一个单独的控制层去解决操作记录的问题
    但是在路由层不可能记录到字段级别,毕竟也不可能在这个地方去查数据
    所以有没啥干净一点的方案,实在是不想在业务逻辑的 controller 里再去逐个字段做对比...

    或许最理想的方案是在 ORM 去做,但是目前对 ORM 的控制力实在有点弱...(go / gorm
    16 replies    2025-06-25 21:28:46 +08:00
    wd
        1
    wd  
       Nov 27, 2021 via iPhone
    数据库 trigger
    MIUIOS
        2
    MIUIOS  
       Nov 27, 2021 via iPhone   ❤️ 1
    我的做法是 binlog ,用 canal 解析 binlog 在写入日志数据库,同步到 es , 完全和业务层解偶,缺点是无法记录用户的 ip 等,不过业务日志只要记录业务行为就行了,剩下的交给系统日志
    taloricag
        3
    taloricag  
    OP
       Nov 27, 2021
    @totoro52 谢谢大佬,但是场景不太符合我,因为我的场景不是完全跟业务解耦,还有条件触发,比如修改了 A 字段需要发个邮件,修改了 B 字段发个通知这种,给我整蒙了
    rrfeng
        4
    rrfeng  
       Nov 27, 2021 via Android
    gorm 有 hooks 啊
    cs419
        5
    cs419  
       Nov 27, 2021
    client 驱动层
    修改 github.com/go-sql-driver/mysql 进行 aop
    fgwmlhdkkkw
        6
    fgwmlhdkkkw  
       Nov 27, 2021 via Android
    只记请求和 sql ,然后再用 sql 解析器,取出来字段。
    MIUIOS
        7
    MIUIOS  
       Nov 27, 2021   ❤️ 1
    @taloricag 一样可以 只要你的表设计有更新人这类似的字段,可以取出来在回表去查通知,如果你的表设计没有更新人和创建人那就不行了
    MIUIOS
        8
    MIUIOS  
       Nov 27, 2021
    @taloricag canal 本身只是负责解析记录,剩下的逻辑还是在自己手上
    Fule
        9
    Fule  
       Nov 29, 2021
    SQL Server 2016+ 有 Temporal Table ,自动维护整行历史记录,一定程度上有助于这类问题,不知道其它数据库是否有类似特性:
    https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2016
    shigella
        10
    shigella  
       Nov 29, 2021
    canal
    cnit
        11
    cnit  
       Nov 29, 2021
    ``` java


    @Component
    @CanalTable("table_name")
    public class OrderHeaderHandler implements EntryHandler {

    @Autowired
    private XxxService xxxService;

    @Override
    public void update(Map<String, String> before, Map<String, String> after, Set<String> updateColumns) {
    //获取需要记录日志的列
    Map<String, String> filedMap = FieldUtils.objectToMap(TableName.class, updateColumns);
    String tableId= before.get("tableId");
    String records = "";
    if (filedMap != null && filedMap.keySet().size() > 0) {
    for (String update : filedMap.keySet()) {
    String comment = filedMap.get(update);
    String beforeValue = before.get(update);
    String afterValue = after.get(update);
    records = records.concat(String.format("%s 由 %s 改为 %s", comment, StringUtils.isEmpty(beforeValue) ? "空" : beforeValue
    , StringUtils.isEmpty(afterValue) ? "空" : afterValue) + ";");
    }
    //记录日志
    OperationRecords operationRecords = new OperationRecords();
    operationRecords.setLinkedId(Long.parseLong(orderId));
    operationRecords.setRecords(records);
    operationRecords.setTableName("container_transport_order_header");
    operationRecords.setCreateTime(new Date());
    operationRecords.setCreateUserId(parseLongUserId(after.get("updateUserId")));
    operationRecordsService.save(operationRecords);
    }
    }



    ```
    onhao
        12
    onhao  
       Nov 29, 2021
    @taloricag 我的方案,可能应用场景有限 用触发器
    https://wuhao.pw/archives/268/

    免去了在应用端敲代码了,仅供参考。
    U87
        13
    U87  
       Jun 24, 2025
    @totoro52 我们业务每个表都有更新人,更新时间,这个可以再回去查没事,ip 等信息咋办,我想到可以塞到 redis 里,把 binlog 解析的内容写到表里的时候,同时去拿 rerdis 里 ip 等信息
    MIUIOS
        14
    MIUIOS  
       Jun 24, 2025
    @U87 你可以根据更新人的登录 IP 去查询,当然前提是有记录登录 IP
    U87
        15
    U87  
       Jun 25, 2025
    @totoro52 这个简单,现在比较麻烦的是,产品的需求是查用户这次修改了哪些表的哪些字段,比如这次请求,改了 10 张表,查的时候怎么查,就是怎么关联
    MIUIOS
        16
    MIUIOS  
       Jun 25, 2025
    @U87 #15 那肯定没办法,binlog 的方式本身就是解耦的, 不带业务逻辑的,你这种最后还是要回归到业务,用 AOP 去做最合适了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5410 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 09:22 · PVG 17:22 · LAX 02:22 · JFK 05:22
    ♥ Do have faith in what you're doing.