在使用Kettle進行數據同步的時候, 共有
1.使用時間戳進行數據增量更新
2.使用數據庫日志進行數據增量更新
3.使用觸發器+快照表 進行數據增量更新
今天要介紹的是第3中方法。
實驗的思路是這樣的,在進行數據同步的時候,
源數據表為A表, A表要對 目標表(target table) B 表和C表進行數據的同步更新。
即A表中的對應字段發生變化之后,
會通過觸發器將對應變化的字段在A表中的主鍵值寫入到一個臨時表temp中(該表作為快照表使用)。
快照表中只有兩個字段,一個是temp_id,是快照表的主鍵,另一個是 A_id,記錄的是在A表中發生變化的字段對應的主鍵的值。
temp( temp_id int primary key auto_increment , A_id int );
接下來,通過對快照表temp進行掃描,把在B表和C表中出現的與temp表中與A_id相匹配的字段,
從B,C兩個目標表中進行移除。
在接下來,讓A表作為源 讓B和C作為目標 對B,C做插入/更新操作;
這樣就實現了A表對B,C兩個表的更新,在后續的操作中可以使用SQL語句將 temp表, 以及觸發器進行 drop操作,以免其浪費內存資源。
在創建 trigger的時候,只要針對A表的 刪除、 更新操作進行創建trigger 即可。
下面來分析一下,對A表進行的不同操作的情況:
1.如果是向A表中插入一行數據: 沒有對應的觸發器,新插入A表的recorder 並沒有被記錄到temp 快照表中,
所以不會對B,C表中對應的字段進行移除操作。(不對 A 表的Insert 操作創建 trigger
可以避免 如果對 A表進行插入的 主鍵值 在 B, C表中 根本找不到,
這樣的話無法 根據temp 中記錄的 主鍵值 對B,C表中的字段進行移除 )
即便不建立觸發器,后續操作中仍舊會因為有 插入/更新的這個 step,對B 表 和 C表進行插入操作的。
2.如果是向A表刪除一行數據的話, 對應創建的觸發器會將 A表中被刪除的 主鍵 字段寫入到 temp這個快照表中去,
接下來,會依照temp表中的字段對B 表和 C 表中的記錄進行移除操作。
而在后續的插入更新操作中,A表中已經將該記錄進行移除了,所以沒有對應的記錄對B,C兩張表進行插入操作。
3. 如果對A表中的某一條記錄 進行 Update 更新操作的話 ,對應Update進行創建的觸發器會 把A表中被更新的記錄
所對應的主鍵值 寫入到快照表 temp中去,
接下來會根據temp表中的主鍵值,對表B 表 C 中的字段進行移除,
然后對B表 C表 依照 A表中的字段進行 插入更新操作。
插入更新操作是這樣的,
如果是主鍵值相等的話, 目標表對應字段 與 源表對應字段 不相同,
就會對目標表字段進行依照 源表進行更新,
如果是某條記錄的 主鍵值 在源表中出現,但是在目標表中沒有出現的話,
則對目標表進行相應的插入操作。(依照源表)
========================================================================
接下來,簡單介紹一下實驗數據:
首先,在Mysql中創建3個表, A B C 表,
對應的字段都是一樣的,對應的數據也都是一樣的(為了簡便......)。

接下來,在Kettle的Spoon中創建下面的流程:
Main
主流程中需要注意的是,在整個流程中,前段的prepare 和 后續 finish 只需要執行一次,
中間的syn是需要重復循環的,至少LZ是這樣設計的,這樣可以使得在循環的這段時期中,
若是A表中的相關字段發生變化的話,會實時地將變化同步到 B C兩個表中。

Main.prepare
在創建觸發器的時候需要注意一下,LZ在實驗的時候,
發現如果觸發器若想觸發 多條操作的時候,
是要寫
" DELIMITER + 分隔符號 "
begin
commands
end
分隔符號
但是,kettle目前的版本是不支持 delimiter的, 也就是寫上之后會報錯,
不寫上,若是執行多條命令語句 后面是必須要加 分號 ";" 來結尾的,
不加分號,也會報錯,
若加上之后,觸發器會默認為 到分號 觸發內容就會結束, 也是出錯的,
LZ的這個步驟之所以沒有出錯是因為,LZ創建的 觸發器只有一條觸發語句,所以沒有用到 delimiter。
如果您想寫多條 觸發語句的話,在delimiter這里要注意一下吧~

Main.syn

Main.syn.delete_B_C_records

Main.syn.A_insert_BandC

這里需要注意的是,在A_insert_into_C這個步驟的時候,對應的目標表中要選擇為c表。
而且,使用觸發器+快照表 進行數據增量更新 主要是通過 :先根據源表中變化(update delete)的記錄 對應刪除目標表中的字段,
然后再,將A表中變化的字段插入到目標表中; 所以整個過程不存在 使用源表 對 目標表進行更新 操作。所以"不執行任何更新" 要勾選 .
Main.finish

收尾工作,主要回收資源,調用Sql語句,執行刪除 快照表、觸發器工作。
接下來我們向A表中,
1.insert 一條記錄,
2.delete一條 同時存在於 A B C表中的記錄,
3.update 一條A表中的記錄。
4.然后對 A表中的 同一條 記錄 先 update 再 delete 它 看結果如何
5.(元數據) A表中還有上一次實驗被存入的,但是B C兩張表中所沒有的 記錄:
原A:

原B:

原C:

after prepare:


modify A :

執行上述的 1 2 3 4 操作后:
A:

snapshot table temp :

對A表的 id=8 進行一次update 一次 delete,
這個temp表需要對A_id進行去除重復記錄操作,這也是為什么要在syn.delete_B_C_records中
去除重復記錄的原因。
為了將整個流程分解,我們來調用Main.syn.delete_B_C_record 這個transformation:
之后顯示的
B:

C:

接下來,使用A表對B,C兩表進行 插入/更新步驟 即 Main.syn.A_insert_BandC
B:
C:
這樣的話,不僅實現了更新,刪除,同步操作,而且同樣把A表中的原來的字段同步到B C兩張表中去了。
如果,不希望將A表中原有數據同步到B,C表中的話,可以通過字段選擇來實現。
當然在具體業務中的情況要比實驗內容復雜得多,這里僅提供簡單的思路,
如果有不恰當之處,敬請指正。
