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_version
和 auth_server_product
表中的 productname
字段。
2.2.1 具体实现
以 navicat 为例进行演示
step 1 : 创建触发器
设计 procut 表,点击触发器,定义触发器的名称,类型选择after update
,表示在product 表中的 productname 更新后 同步更新其他表。
step 2 : sql 定义触发器行为
编写具体的sql语句定义触发器行为,在这个例子中,期望在 productname
更新时,自动更新 mobile_version
和 auth_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关联字段同步更新的资料请关注代码网其它相关文章!
发表评论