MySQL多个表的关联字段实现同步更新的解决方案

 更新时间:2024年11月19日 11:50:42   作者:离开地球表面_99  
在对数据库表结构进行设计时,为了提高查询效率,会进行一些反规范化设计,如:设计一些冗余字段,但这样可能会存在数据同步问题,故本文给大家介绍了MySQL多个表的关联字段实现同步更新的解决方案,需要的朋友可以参考下

1. 背景

在对数据库表结构进行设计时,为了提高查询效率,会进行一些反规范化设计,如:设计一些冗余字段。但这样可能会存在数据同步问题,当源表字段值更新时,冗余字段值也需要同步更新。

现有产品表 product ,移动端版本 mobile_version ,授权绑定产品表auth_server_product 三个表,这三个表有一个共同字段 productName,期望当 product 表中的 productName 字段的值改变时,将该字段修改后的值同步更新到 mobile_version,auth_server_product 两个表中。

1.1 表结构定义

1.1.1 product 表

CREATE TABLE `product`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `productName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO `product` VALUES (1, '产品A');
INSERT INTO `product` VALUES (2, '产品B');
INSERT INTO `product` VALUES (3, '产品C');

1.1.2 auth_server_product 表

CREATE TABLE `auth_server_product`  (
  `id` int(0) NOT NULL,
  `authId` int(0) NULL DEFAULT NULL,
  `productId` int(0) NULL DEFAULT NULL,
  `productName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO `auth_server_product` VALUES (1, 1, 1, '产品A');
INSERT INTO `auth_server_product` VALUES (2, 1, 2, '产品B');
INSERT INTO `auth_server_product` VALUES (3, 1, 3, '产品C');

1.1.3 mobile_version 表

CREATE TABLE `mobile_version`  (
  `id` int(0) NOT NULL,
  `mobile_version` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `productId` int(0) NULL DEFAULT NULL,
  `productName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;


INSERT INTO `mobile_version` VALUES (1, 'V1.0.0', 1, '产品A');
INSERT INTO `mobile_version` VALUES (2, 'V1.0.1', 1, '产品A');

2. 解决方案

2.1 应用层代码中更新

代码层实现数据同步逻辑,在更新 product 表中的 productName 字段时,同步更新auth_server_product 与 mobile_version 两表中的字段值。大致逻辑如下:

@Transactional
public void updateProductName(String oldProductName, String newProductName) {
    // 更新 product 表中的 productName
    productRepository.updateProductName(oldProductName, newProductName);
    
    // 同步更新 mobile_version 表
    mobileVersionRepository.updateProductName(oldProductName, newProductName);

    // 同步更新 auth_server_product 表
    authServerProductRepository.updateProductName(oldProductName, newProductName);
}

该种方案的劣势

  • 代码复杂,耦合性强;
  • 数据不一致:如果同步逻辑没有被正确实现或处理,可能会导致数据不一致。

2.2 利用MySQL提供的触发器功能

MySQL 提供了触发器功能,在随某个表进行记录的新增(INSERT)、修改(UPDATE) 或是删除( DELETE) 操作时,会自动触发相应的操作。

针对上述场景中的这个问题,可以在 product 表设置触发器,在 UPDATE 操作时,通过触发器来同步更新 mobile_versionauth_server_product 表中的 productName 字段。

2.2.1 具体实现

Navicat 为例进行演示

Step 1 : 创建触发器

设计 procut 表,点击触发器,定义触发器的名称,类型选择AFTER UPDATE,表示在product 表中的 productName 更新后 同步更新其他表。

Step 2 : SQL 定义触发器行为

编写具体的SQL语句定义触发器行为,在这个例子中,期望在 productName 更新时,自动更新 mobile_versionauth_server_product 表中的 productName。SQL 下:

BEGIN
    -- 如果 productName 发生变化
    IF OLD.productName <> NEW.productName THEN
        -- 更新 mobile_version 表中的 productName
        UPDATE mobile_version
        SET productName = NEW.productName
        WHERE productName = OLD.productName;
        
        -- 更新 auth_server_product 表中的 productName
        UPDATE auth_server_product
        SET productName = NEW.productName
        WHERE productName = OLD.productName;
    END IF;
END 

Step 3 : 验证

  • show triggers,可查看当前数据库中的触发器,验证触发器是否创建成功。

  • 执行更新语句,验证触发器的定义能否达到期望的效果。
update product set productName = '产品AA' where id = '1'

可以看到,当 product 表中的 productName 值更新后,mobile_version 与 auth_server_product 对应的 productName 值同步更新。

2.2.2 关于触发器

  • 触发事件:触发器会在某个特定事件发生时被触发。常见的触发事件包括:

    • INSERT:在插入数据时触发。
    • UPDATE:在更新数据时触发。
    • DELETE:在删除数据时触发。
  • 触发时机:触发器可以定义在数据事件发生的 BEFORE)或 AFTER)执行。

    • BEFORE:触发器在数据变更之前执行。
    • AFTER:触发器在数据变更之后执行。
  • 触发器的作用域:触发器通常绑定到某个表上,并且只能在该表的数据操作时触发。它不能跨表执行,也不能直接返回数据。

以上就是MySQL多个表的关联字段实现同步更新的解决方案的详细内容,更多关于MySQL关联字段同步更新的资料请关注脚本之家其它相关文章!

相关文章

  • 浅谈MySQL如何优雅的做大表删除

    浅谈MySQL如何优雅的做大表删除

    这篇文章主要介绍了浅谈MySQL如何优雅的做大表删除,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • MySQL字段定义时的属性设置方式

    MySQL字段定义时的属性设置方式

    这篇文章主要介绍了MySQL字段定义时的属性设置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • SQL和NoSQL之间的区别总结

    SQL和NoSQL之间的区别总结

    在本篇内容里我们给大家精选了关于SQL和NoSQL之间的区别的总结内容,对此有需要的朋友们跟着学习下。
    2019-02-02
  • MySQL如何查找树形结构中某个节点及其子节点

    MySQL如何查找树形结构中某个节点及其子节点

    这篇文章主要介绍了MySQL如何查找树形结构中某个节点及其子节点问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 手把手教你使用Navicat生成MySQL测试数据

    手把手教你使用Navicat生成MySQL测试数据

    Navicat是一套快速、可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设,下面这篇文章主要给大家介绍了关于使用Navicat生成MySQL测试数据的相关资料,需要的朋友可以参考下
    2023-05-05
  • MySQL5.5.21安装配置教程(win7)

    MySQL5.5.21安装配置教程(win7)

    这篇文章主要以图文结合的方式介绍了Win7系统下安装MySQL5.5.21的具体过程,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • MySQL慢查询中的commit慢和binlog中慢事务的区别

    MySQL慢查询中的commit慢和binlog中慢事务的区别

    这篇文章主要介绍了MySQL慢查询中的commit慢和binlog中慢事务的差异,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Ubuntu上mysql的安装及使用(通用版)

    Ubuntu上mysql的安装及使用(通用版)

    今天小编就为大家分享一篇关于Ubuntu上mysql的安装及使用(通用版),小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • windows-mysql8.0.15如何修改密码、重置密码

    windows-mysql8.0.15如何修改密码、重置密码

    本文详细介绍了在Windows环境下,如何修改或重置MySQL 8.0.15版本的用户密码,首先,需要停止MySQL服务并以管理员权限打开cmd窗口,然后开启跳过密码验证的MySQL服务,接着,通过新的命令窗口登录MySQL,并选择相应的数据库进行密码修改或重置
    2024-10-10
  • MySQL中的时区设置方式

    MySQL中的时区设置方式

    这篇文章主要介绍了MySQL中的时区设置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11

最新评论