同時使用數(shù)據(jù)庫鏈和序列時的注意事項

字號:

正常情況下,在一條語句中如果同時包括數(shù)據(jù)庫鏈和序列,就會出現(xiàn)潛在的問題,而Oracle的官方文檔在這里描述的并不是十分清楚。
    以下通過一個例子對同時包括數(shù)據(jù)庫鏈和序列的幾種情況分別進行說明。
    首先,大家需要構造一個測試的環(huán)境(注:兩個數(shù)據(jù)庫的GLOBAL_NAMES均為TRUE):
    SQL> conn scott/tiger@yangtk
    已連接。
    SQL> create table test_on_yangtk (id number);
    表已創(chuàng)建。
    SQL> insert into test_on_yangtk values (1);
    已創(chuàng)建 1 行。
    SQL> commit;
    提交完成。
    SQL> create sequence seq_on_yangtk;
    序列已創(chuàng)建。
    SQL> conn yangtk/yangtk@test4
    已連接。
    SQL> create table test_on_test4 (id number);
    表已創(chuàng)建。
    SQL> insert into test_on_test4 values (1);
    已創(chuàng)建 1 行。
    SQL> commit;
    提交完成。
    SQL> create sequence seq_on_test4;
    序列已創(chuàng)建。
    SQL> create database link yangtk connect to scott identified by tiger using 'yangtk';
    數(shù)據(jù)庫鏈接已創(chuàng)建。
    對于簡單的查詢語句,可以分為以下四種情況。
    1.從本地表中讀取數(shù)據(jù),并引用本地序列。
    SQL> select seq_on_test4.nextval from test_on_test4;
    NEXTVAL
    ----------
    1
    2.從本地表中讀取數(shù)據(jù),但訪問遠端序列,這時,需要在序列后面加上數(shù)據(jù)庫鏈名稱。
    SQL> select seq_on_yangtk.nextval@yangtk from test_on_test4;
    NEXTVAL
    ----------
    1
    3.讀取遠端數(shù)據(jù)表中數(shù)據(jù),同時訪問遠端序列。
    SQL> select seq_on_yangtk.nextval@yangtk from test_on_yangtk@yangtk;
    NEXTVAL
    ----------
    2
    4.讀取遠端數(shù)據(jù)表中數(shù)據(jù),但是訪問本地序列。
    SQL> select seq_on_test4.nextval from test_on_yangtk@yangtk;
    NEXTVAL
    ----------
    2
    經過測試,此四種情況工作都很正常。
    下面,我們來考慮分布式事務——以INSERT INTO SELECT為例。
    由于INSERT的表可以是本地表,也可以是遠端表,對于每種情況,對應的子查詢語句都可能包含上面四種情況,下面我們來分別進行具體的分析
    一、插入本地表
    1.從本地表中讀取數(shù)據(jù),并引用本地序列
    SQL> insert into test_on_test4 select seq_on_test4.nextval from test_on_test4;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    2.從本地表中讀取數(shù)據(jù),但訪問遠端序列
    SQL> insert into test_on_test4 select
    seq_on_yangtk.nextval@yangtk from test_on_test4;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    3.讀取遠端數(shù)據(jù)表中數(shù)據(jù),同時訪問遠端序列。
    SQL> insert into test_on_test4 select seq_on_yangtk.nextval@yangtk from test_on_yangtk@yangtk;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    4.讀取遠端數(shù)據(jù)表中數(shù)據(jù),但是訪問本地序列。
    SQL> insert into test_on_test4 select
    seq_on_test4.nextval from test_on_yangtk@yangtk;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    經測試,插入本地表的四種情況,沒有出錯
    二、插入遠端表
    1.從本地表中讀取數(shù)據(jù),并引用本地序列
    SQL> insert into test_on_yangtk@yangtk select
    seq_on_test4.nextval from test_on_test4;
    insert into test_on_yangtk@yangtk select
    seq_on_test4.nextval from test_on_test4
    *
    ERROR 位于第 1 行:
    ORA-02289: 序列(號)不存在
    ORA-02063: 緊接著line(源于TEST4)
    ORA-02063: 緊接著2 lines(源于YANGTK)
    2.從本地表中讀取數(shù)據(jù),但訪問遠端序列
    SQL> insert into test_on_yangtk@yangtk
    select seq_on_yangtk.nextval@yangtk from test_on_test4;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    3.讀取遠端數(shù)據(jù)表中數(shù)據(jù),同時訪問遠端序列。
    SQL> insert into test_on_yangtk@yangtk
    select seq_on_yangtk.nextval@yangtk from test_on_yangtk@yangtk;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    4.讀取遠端數(shù)據(jù)表中數(shù)據(jù),但是訪問本地序列。
    SQL> insert into test_on_yangtk@yangtk select seq_on_test4.nextval from test_on_yangtk@yangtk;
    insert into test_on_yangtk@yangtk select seq_on_test4.nextval from test_on_yangtk@yangtk
    *
    ERROR 位于第 1 行:
    ORA-02289: 序列(號)不存在
    ORA-02063: 緊接著line(源于TEST4)
    ORA-02063: 緊接著2 lines(源于YANGTK)
    根據(jù)測試,第一種情況和第四種情況出現(xiàn)了相同的錯誤。
    在和其他所有沒有報錯的情況比較后,可以得到這樣的結論:當插入遠端數(shù)據(jù)表,并使用本地序列時會出現(xiàn)錯誤。
    Oracle的error文檔上這樣描述2289錯誤的:
    ORA-02289 sequence does not exist
    Cause: The specified sequence does not exist,
    or the user does not have the required
    privilege to perform this operation.
    Action: Make sure the sequence name is correct,
    and that you have the right to perform
    the desired operation on this sequence.
    根據(jù)目前的錯誤以及Oracle給出的錯誤原因,初步懷疑對于這種插入遠端數(shù)據(jù)表的分布式事務,實際上是在遠端上執(zhí)行的。因此YANGTK上的scott用戶找不到SEQ_ON_TEST4這個序列。
    給YANGTK上的scott用戶增加一個指向TEST4上yangtk用戶的數(shù)據(jù)庫鏈。
    SQL> conn scott/tiger@yangtk
    已連接。
    SQL> create database link test4 connect to
    yangtk identified by yangtk using 'test4';
    數(shù)據(jù)庫鏈接已創(chuàng)建。
    SQL> conn yangtk/yangtk@test4
    已連接。
    SQL> insert into test_on_yangtk@yangtk select
    seq_on_test4.nextval from test_on_test4;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    SQL> insert into test_on_yangtk@yangtk select
    seq_on_test4.nextval from test_on_yangtk@yangtk;
    已創(chuàng)建 1 行。
    SQL> rollback;
    回退已完成。
    在建立數(shù)據(jù)庫鏈之后,重新執(zhí)行錯誤的語句,這次執(zhí)行沒有出現(xiàn)錯誤。
    總結:
    假如在一條語句中同時使用數(shù)據(jù)庫鏈和序列,大家需要注意的是:目前可能不僅需要一條到遠端的數(shù)據(jù)庫鏈,還可能同時需要一個從遠端到本地的數(shù)據(jù)庫鏈。