2008-09-04 15 views
6

मेरे पास 5 एप्लिकेशन सर्वर पर एक वितरित जावा एप्लिकेशन चल रहा है। सर्वर 6 वें मशीन पर चल रहे एक ही ओरेकल 9आई डेटाबेस का उपयोग करते हैं।एक वितरित वातावरण में ओरेकल अनुक्रम आईडी-एस को प्रीफेच करने के लिए कैसे करें

एप्लिकेशन को अनुक्रम से 100 आईडी के बैच को प्रीफ़ेच करने की आवश्यकता है। यह एक एकल पिरोया, गैर वितरित वातावरण में करने के लिए अपेक्षाकृत आसान है, तुम सिर्फ इन क्वेरी भेज सकते हैं:

select seq.nextval from dual; 
alter sequence seq increment by 100; 
select seq.nextval from dual; 

पहले चयन को हासिल करेगा पहले अनुक्रम ID कि आवेदन का उपयोग कर सकते हैं, दूसरे का चयन रिटर्न पिछले एक जिसका इस्तेमाल किया जा सकता है।

चीजें एक बहुप्रचारित वातावरण में और अधिक दिलचस्प हो जाती हैं। आप यह सुनिश्चित नहीं कर सकते कि दूसरे चयन से पहले एक और थ्रेड क्रमशः 100 तक अनुक्रम नहीं बढ़ाता है। जावा पक्ष पर पहुंच को सिंक्रनाइज़ करके इस समस्या को हल किया जा सकता है - आप केवल एक थ्रेड को एक ही समय में आईडी लाने शुरू करते हैं।

स्थिति सिंक्रनाइज़ नहीं हो सकती है जब स्थिति सिंक्रनाइज़ नहीं हो सकती है क्योंकि एप्लिकेशन के कुछ हिस्सों एक ही भौतिक मशीन पर भी नहीं, एक ही JVM पर नहीं चलते हैं। मुझे मंचों पर कुछ संदर्भ मिले कि दूसरों को भी इस समस्या को हल करने में समस्याएं हैं, लेकिन कोई भी जवाब वास्तव में उचित नहीं होने का उल्लेख नहीं कर रहा है।

क्या समुदाय इस समस्या का समाधान प्रदान कर सकता है?

कुछ अधिक जानकारी:

  • मैं वास्तव में लेनदेन अलगाव स्तर के साथ नहीं खेल सकते हैं। मैं जेपीए का उपयोग करता हूं और परिवर्तन पूरे आवेदन को प्रभावित करेगा, न केवल prefetching प्रश्नों और यह मेरे लिए स्वीकार्य नहीं है।
  • PostgreSQL पर मैं निम्नलिखित कर सकता है:

    चयन setval ('seq', nextval ('seq') + n - 1)

  • मैथ्यू द्वारा समाधान काम करता है जब आप एक निश्चित उपयोग कर सकते हैं वृद्धि मूल्य (जो मेरे मामले में पूरी तरह से स्वीकार्य है)। हालांकि, क्या कोई समाधान है जब आप वृद्धि के आकार को ठीक नहीं करना चाहते हैं, लेकिन इसे गतिशील रूप से समायोजित करना चाहते हैं?

उत्तर

10

क्यों हर समय अनुक्रम के रूप में अनुक्रम नहीं है? प्रत्येक "nextval" आप 100 अनुक्रम संख्या अपने उदाहरण पर

SQL> create sequence so_test start with 100 increment by 100 nocache; 

Sequence created. 

SQL> select so_test.nextval - 99 as first_seq, so_test.currval as last_seq from dual; 

FIRST_SEQ LAST_SEQ 
---------- ---------- 
     1  100 

SQL>/

FIRST_SEQ LAST_SEQ 
---------- ---------- 
     101  200 

SQL>/

FIRST_SEQ LAST_SEQ 
---------- ---------- 
     201  300 

SQL> 

एक नोट के साथ काम करने देता है .. DDL से सावधान रहें .. यह एक अंतर्निहित प्रतिबद्ध

की प्रतिबद्ध DDL द्वारा उत्पादित उदाहरण का उत्पादन करेगा

SQL> select * from xx; 

no rows selected 

SQL> insert into xx values ('x'); 

1 row created. 

SQL> alter sequence so_test increment by 100; 

Sequence altered. 

SQL> rollback; 

Rollback complete. 

SQL> select * from xx; 

Y 
----- 
x 

SQL> 
+0

ग्रेट उत्तर: ओ) – Andrew

1

मैथ्यू का सही दृष्टिकोण यहां है। मेरी राय में, प्रत्येक एप्लिकेशन के बाद अनुक्रम के वर्तमान मूल्य को रीसेट करने के लिए एप्लिकेशन बहुत असामान्य है। जो भी आपको पहले की आवश्यकता है, उसमें वृद्धि आकार निर्धारित करने के लिए बहुत अधिक पारंपरिक।

इसके अलावा, इस तरह से अधिक प्रदर्शन करने वाला है। अनुक्रम से अगली कड़ी का चयन ओरेकल में एक अत्यधिक अनुकूलित ऑपरेशन है, जबकि अनुक्रम को बदलने के लिए डीडीएल चलाना बहुत महंगा है।

मुझे लगता है कि वास्तव में आपकी संपादित प्रश्न में अंतिम बिंदु का जवाब नहीं है ...

3

क्यों आप पहली जगह में अनुक्रम आईडी लाने के लिए की जरूरत है? ज्यादातर मामलों में आप एक टेबल में डालेंगे और आईडी वापस कर देंगे।

insert into t (my_pk, my_data) values (mysequence.nextval, :the_data) 
returning my_pk into :the_pk; 

ऐसा लगता है कि आप प्रसंस्करण को पूर्व-अनुकूलित करने की कोशिश कर रहे हैं।

यदि आपको वास्तव में आईडी को पूर्व-प्राप्त करने की आवश्यकता है तो बस अनुक्रम 100 बार कॉल करें। अनुक्रम का पूरा बिंदु यह है कि यह संख्या को प्रबंधित करता है। आपको यह मानना ​​नहीं है कि आप लगातार 100 नंबर प्राप्त कर सकते हैं।

1

जब आप एक निश्चित आकार वृद्धि नहीं चाहते हैं, तो अनुक्रम वास्तव में आप जो भी कर रहे हैं, वास्तव में नहीं हैं, वे वास्तव में गारंटी देते हैं कि आपको हमेशा प्राप्त होने वाले एक अद्वितीय नंबर की तुलना में एक अद्वितीय संख्या मिल जाएगी। हमेशा संभावना है कि आप अंतराल के साथ समाप्त हो जाएंगे, और आप वास्तव में उड़ान भरने या प्रभावी ढंग से बढ़ती राशि को समायोजित नहीं कर सकते हैं।

मैं वास्तव में किसी भी मामले के बारे में सोच नहीं सकता जहां मुझे इस तरह की चीज करना पड़ा, लेकिन शायद सबसे आसान तरीका सिर्फ "वर्तमान" नंबर को स्टोर करने और इसे आवश्यकतानुसार अपडेट करने का सबसे आसान तरीका है।

ऐसा कुछ।

drop table t_so_test; 

create table t_so_test (curr_num number(10)); 

insert into t_so_test values (1); 
create or replace procedure p_get_next_seq (inc IN NUMBER, v_next_seq OUT NUMBER) As 
BEGIN 
    update t_so_test set curr_num = curr_num + inc RETURNING curr_num into v_next_seq; 
END; 
/


SQL> var p number; 
SQL> execute p_get_next_seq(100,:p); 

PL/SQL procedure successfully completed. 

SQL> print p; 

     P 
---------- 
     101 

SQL> execute p_get_next_seq(10,:p);  

PL/SQL procedure successfully completed. 

SQL> print p; 

     P 
---------- 
     111 

SQL> execute p_get_next_seq(1000,:p); 

PL/SQL procedure successfully completed. 

SQL> print p; 

     P 
---------- 
     1111 

SQL> 
संबंधित मुद्दे