程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SyBase數據庫 >> SyBase綜合文章 >> MobiLink開發資源集之同步數據沖突處理

MobiLink開發資源集之同步數據沖突處理

編輯:SyBase綜合文章

步驟清單

 

要解決沖突問題,我們應首先理解何謂沖突。

 

在向統一數據庫中上載行時可能會發生沖突。如果兩個用戶修改不同遠程數據庫中相同的行,則當這兩行中的第二個到達 MobiLink 同步服務器時將出現沖突。在沖突發生時,您應定義一個過程以計算正確值,或至少使用日志文件記錄沖突。

 

在同步的下載階段,遠程數據庫中不會出現沖突。如果下載的行中包含一個新的主鍵,則該行的值將插入到新的一行。如果該主鍵與一個現有行的主鍵相匹配,則會更新該行中的值。

 

沖突與錯誤是兩個不同的概念。沖突處理是應用程序應該包含的一部分。

 

只有在更新行的過程中才會檢測到沖突。嘗試更新自上一次同步後已更新或刪除的行將會導致沖突。缺省情況下:

 

*如果在嘗試插入一行時發現此行已經插入,則會導致錯誤。

 

*如果在嘗試刪除一行時發現此行已經刪除,則此嘗試刪除的操作將被忽略。

 

這些是為方便操作而定義的內置行為。如果需要不同的行為,可以使用一個或多個上載事件自行實現。

 

我們在demo的前半部分展示了有沖突而未解決的情況。當兩個不同的客戶端分別將相同的數據進行不同更改後,再在不同時間上載,後上載的數據成了最終結果。這可能是我們不想要的情況。我們需要對沖突進行一定的檢測、然後再根據我們的用戶規則進行處理。

 

在 MobiLink 客戶端向 MobiLink 同步服務器發送一個更新後的行時,發送的數據中不僅包含該行的新值(後映像),而且還將包含舊行值的副本(前映像)。如果前映像與統一數據庫中的當前值不匹配,表示檢測到了沖突。

 

 

檢測沖突的方法有兩種:

*定義一個 upload_fetch 腳本。

 

*定義一個 upload_update 腳本,該腳本在 WHERE 子句中包含所有非主鍵列。

 

如果為同一個表定義這兩個腳本,則只使用 upload_fetch 腳本。

 

僅當使用 upload_fetch 腳本或適當的 upload_update 腳本時,MobiLink 同步服務器才檢測沖突。如果提供了 upload_fetch 腳本,MobiLink 同步服務器會將上載的前映像與 upload_fetch 腳本返回的包含相同主鍵值的行值進行比較。如果存在前映像中的值與當前統一數據庫中的值不匹配的情況,則表示 MobiLink 同步服務器檢測到了沖突。

 

我們這裡用upload_fetch:

 

CALL ml_add_table_script(
'remote1',
'upload_fetch',
'SELECT empno, empname, gender, deptno, last_modifIEd FROM emp WHERE empno = ?'
)

出現沖突時,可以使用臨時表(或永久表)和 resolve_conflict 腳本加以解決。

 

例如,我們可以先建兩個臨時表,然後在upload_old_row_insert表事件中把統一數據庫的舊值插入專門存放舊值的臨時表,然後再 upload_new_row_insert表事件中把想要更新的值插入專門存放新值的臨時表。接下來就可以在resolve_conflict表事件中解決沖突了。

 

當然,除了通過resolve_conflict事件解決沖突,我們也可利用upload_update、end_upload來解決沖突。在本部分的屏幕錄像中,我們先展示了沒有自定義沖突處理時候MobiLink對沖突的默認解決方案,即後者決定的策略。在此之後,我們又自定義了新的MobiLink沖突解決方案,讓部門號較小的更新成為最終值。

 

本部分的腳本如下:

 

先建立兩個目錄:remote1 & remote2。

 

把數據庫分別拷貝。

 

啟動個數據庫,中心叫center,其余兩個一個叫remote1,一個叫remote2。

 

重新建立remote1和remote2的ODBC

對3個庫分別執行:

 

ALTER TABLE emp ADD last_modified 
TIMESTAMP DEFAULT TIMESTAMP

 

dbisql:

remote1:


CREATE PUBLICATION Lab_05
(
TABLE emp
)

CREATE SYNCHRONIZATION USER "remote1"

CREATE SYNCHRONIZATION SUBSCRIPTION TO Lab_05
FOR "remote1"
TYPE 'TCPIP'
ADDRESS 'host=localhost;port=2439'
OPTION ScriptVersion='remote1'


 

 

remote2:

CREATE PUBLICATION Lab_05
(
TABLE emp
)

CREATE SYNCHRONIZATION USER "remote2"

ALTER SYNCHRONIZATION SUBSCRIPTION TO Lab_05
FOR "remote2"
TYPE 'TCPIP'
ADDRESS 'host=localhost;port=2439'
OPTION ScriptVersion='remote1'



center:

CALL ml_add_table_script('remote1', 'emp',
 'download_cursor', 'SELECT * FROM emp WHERE 
last_modifIEd > ?');

 

CALL ml_add_table_script('remote1', 'emp', 
'upload_update', 'UPDATE emp SET empname=?, 
gender=?, deptno=? WHERE empno=?');


COMMIT

 

 

命令行下:

 

dbmlsrv9 -c "dsn=center" -v+ -x tcpip -dl -o mlserver.mls -zu+

dbmlsync -c "dsn=remote1" -v -o dbmlsync1.out -e "sv=remote1"

dbmlsync -c "dsn=remote2" -v -o dbmlsync2.out -e "sv=remote1"

 

對remote2:

 

 

UPDATE emp SET deptno = '0005' WHERE empno = 1

COMMIT

再次同步remote2

 

 

dbmlsync -c "dsn=remote2" -v -o dbmlsync2.out -e "sv=remote1"

 

 

對remote1

 

UPDATE emp SET deptno = '0002' WHERE empno = 1

COMMIT

 

 

 

 

同步remote1

 

dbmlsync -c "dsn=remote1" -v -o 
dbmlsync1.out -e "sv=remote1"

 

對center:

 

 

CREATE GLOBAL TEMPORARY TABLE emp_new(
empno INTEGER NOT NULL PRIMARY KEY,
empname VARCHAR(20),
gender BIT,
deptno CHAR(4),
last_modified TIMESTAMP);
CREATE GLOBAL TEMPORARY TABLE emp_old(
empno INTEGER NOT NULL PRIMARY KEY,
empname VARCHAR(20),
gender BIT,
deptno CHAR(4),
last_modified TIMESTAMP)

CALL ml_add_connection_script(
'remote1',
'end_upload',
'DROP TABLE emp_new;
DROP TABLE emp_old');

CALL ml_add_table_script(
'remote1',
'upload_fetch',
'SELECT empno, empname, gender, deptno, 
last_modifIEd FROM emp WHERE empno = ?'
)

CALL ml_add_table_script(
'remote1',
'emp',
'upload_old_row_insert',
'INSERT INTO emp_old VALUES(?,?,?,?)');

CALL ml_add_table_script(
'remote1',
'emp',
'upload_new_row_insert',
'INSERT INTO emp_new VALUES(?,?,?,?)');

CALL ml_add_table_script(
'remote1',
'emp',
'resolve_conflict',
'CALL ResolveConflictDemo()');

COMMIT;


ALTER OR REPLACE PROCEDURE ResolveConflictDemo()
BEGIN
UPDATE emp e
SET e.deptno = en.deptno
FROM emp_new en
WHERE e.empno = en.empno
AND en.deptno < e.deptno;

DELETE FROM emp_new;
DELETE FROM emp_old;
END;
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved