MySQL多個(gè)表的關(guān)聯(lián)字段實(shí)現(xiàn)同步更新的解決方案
1. 背景
在對數(shù)據(jù)庫表結(jié)構(gòu)進(jìn)行設(shè)計(jì)時(shí),為了提高查詢效率,會(huì)進(jìn)行一些反規(guī)范化設(shè)計(jì),如:設(shè)計(jì)一些冗余字段。但這樣可能會(huì)存在數(shù)據(jù)同步問題,當(dāng)源表字段值更新時(shí),冗余字段值也需要同步更新。
現(xiàn)有產(chǎn)品表 product
,移動(dòng)端版本 mobile_version
,授權(quán)綁定產(chǎn)品表auth_server_product
三個(gè)表,這三個(gè)表有一個(gè)共同字段 productName,期望當(dāng) product 表中的 productName 字段的值改變時(shí),將該字段修改后的值同步更新到 mobile_version,auth_server_product 兩個(gè)表中。
1.1 表結(jié)構(gòu)定義
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, '產(chǎn)品A'); INSERT INTO `product` VALUES (2, '產(chǎn)品B'); INSERT INTO `product` VALUES (3, '產(chǎn)品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, '產(chǎn)品A'); INSERT INTO `auth_server_product` VALUES (2, 1, 2, '產(chǎn)品B'); INSERT INTO `auth_server_product` VALUES (3, 1, 3, '產(chǎn)品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, '產(chǎn)品A'); INSERT INTO `mobile_version` VALUES (2, 'V1.0.1', 1, '產(chǎn)品A');
2. 解決方案
2.1 應(yīng)用層代碼中更新
在代碼層實(shí)現(xiàn)數(shù)據(jù)同步邏輯,在更新 product 表中的 productName 字段時(shí),同步更新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); }
該種方案的劣勢:
- 代碼復(fù)雜,耦合性強(qiáng);
- 數(shù)據(jù)不一致:如果同步邏輯沒有被正確實(shí)現(xiàn)或處理,可能會(huì)導(dǎo)致數(shù)據(jù)不一致。
2.2 利用MySQL提供的觸發(fā)器功能
MySQL 提供了觸發(fā)器功能,在隨某個(gè)表進(jìn)行記錄的新增(INSERT
)、修改(UPDATE
) 或是刪除( DELETE
) 操作時(shí),會(huì)自動(dòng)觸發(fā)相應(yīng)的操作。
針對上述場景中的這個(gè)問題,可以在 product
表設(shè)置觸發(fā)器,在 UPDATE
操作時(shí),通過觸發(fā)器來同步更新 mobile_version
和 auth_server_product
表中的 productName
字段。
2.2.1 具體實(shí)現(xiàn)
以 Navicat 為例進(jìn)行演示
Step 1 : 創(chuàng)建觸發(fā)器
設(shè)計(jì) procut 表,點(diǎn)擊觸發(fā)器,定義觸發(fā)器的名稱,類型選擇AFTER UPDATE
,表示在product 表中的 productName 更新后 同步更新其他表。
Step 2 : SQL 定義觸發(fā)器行為
編寫具體的SQL語句定義觸發(fā)器行為,在這個(gè)例子中,期望在 productName
更新時(shí),自動(dòng)更新 mobile_version
和 auth_server_product
表中的 productName
。SQL 下:
BEGIN -- 如果 productName 發(fā)生變化 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 : 驗(yàn)證
show triggers
,可查看當(dāng)前數(shù)據(jù)庫中的觸發(fā)器,驗(yàn)證觸發(fā)器是否創(chuàng)建成功。
- 執(zhí)行更新語句,驗(yàn)證觸發(fā)器的定義能否達(dá)到期望的效果。
update product set productName = '產(chǎn)品AA' where id = '1'
可以看到,當(dāng) product 表中的 productName 值更新后,mobile_version 與 auth_server_product 對應(yīng)的 productName 值同步更新。
2.2.2 關(guān)于觸發(fā)器
觸發(fā)事件:觸發(fā)器會(huì)在某個(gè)特定事件發(fā)生時(shí)被觸發(fā)。常見的觸發(fā)事件包括:
INSERT
:在插入數(shù)據(jù)時(shí)觸發(fā)。UPDATE
:在更新數(shù)據(jù)時(shí)觸發(fā)。DELETE
:在刪除數(shù)據(jù)時(shí)觸發(fā)。
觸發(fā)時(shí)機(jī):觸發(fā)器可以定義在數(shù)據(jù)事件發(fā)生的 前(
BEFORE
)或 后(AFTER
)執(zhí)行。BEFORE
:觸發(fā)器在數(shù)據(jù)變更之前執(zhí)行。AFTER
:觸發(fā)器在數(shù)據(jù)變更之后執(zhí)行。
觸發(fā)器的作用域:觸發(fā)器通常綁定到某個(gè)表上,并且只能在該表的數(shù)據(jù)操作時(shí)觸發(fā)。它不能跨表執(zhí)行,也不能直接返回?cái)?shù)據(jù)。
以上就是MySQL多個(gè)表的關(guān)聯(lián)字段實(shí)現(xiàn)同步更新的解決方案的詳細(xì)內(nèi)容,更多關(guān)于MySQL關(guān)聯(lián)字段同步更新的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
win2008下mysql8.0.11升級mysql8.0.17版本詳細(xì)步驟
這篇文章主要為大家詳細(xì)介紹了win2008下mysql8.0.11升級mysql8.0.17版本詳細(xì)步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08MySQL5.6.31 winx64.zip 安裝配置教程詳解
這篇文章主要介紹了MySQL5.6.31 winx64.zip 安裝配置教程詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02Ubuntu Server下MySql數(shù)據(jù)庫備份腳本代碼
為了mysql數(shù)據(jù)庫的安全,我們需要定時(shí)備份mysql數(shù)據(jù)庫,這里提供下腳本代碼,需要的朋友可以參考下2013-06-06數(shù)據(jù)庫連接池以及sequelize實(shí)現(xiàn)增刪改查等操作指南
Sequelize的連接需要傳入?yún)?shù),并且可以配置開啟線程池、讀寫分庫等操作,下面這篇文章主要給大家介紹了關(guān)于數(shù)據(jù)庫連接池以及sequelize實(shí)現(xiàn)增刪改查等操作的相關(guān)資料,需要的朋友可以參考下2022-08-08Mysql8報(bào)錯(cuò)this is incompatible with sql_mo
這篇文章主要介紹了Mysql8報(bào)錯(cuò)this is incompatible with sql_mode=only_full_group_by問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01MySQL權(quán)限USAGE和ALL PRIVILEGES的用法
本文主要介紹了MySQL權(quán)限USAGE和ALL PRIVILEGES的用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09