PostgreSQL में टेबल डेटा को एटमॉली से कैसे बदलें


14

मैं SELECTप्रक्रिया के दौरान किसी भी आने वाले बयान को प्रभावित किए बिना, तालिका की संपूर्ण सामग्री को प्रतिस्थापित करना चाहता हूं ।

उपयोग के मामले में एक मेज है जो मेलबॉक्स जानकारी संग्रहीत करती है जो नियमित रूप से निकाली जाती है, और पोस्टग्रेसीक्यूएल तालिका में संग्रहीत करने की आवश्यकता होती है। कई क्लाइंट ऐसे एप्लिकेशन का उपयोग कर रहे हैं जो लगातार उसी टेबल को क्वेरी कर रहे हैं।

आम तौर पर, मैं कुछ ऐसा करूंगा (आने वाला स्यूडोकोड) ...

BEGIN TRANSACTION
TRUNCATE TABLE
INSERT INTO
COMMIT

लेकिन दुर्भाग्य से इस प्रक्रिया के दौरान तालिका को पढ़ा नहीं जा सकता है; समय INSERT INTOपूरा होने में समय लगता है। मेज पर ताला लगा है।

MySQL में, मैंने RENAME TABLEइन मुद्दों से बचने के लिए अपने परमाणु कमांड का उपयोग किया होगा ...

CREATE TABLE table_new LIKE table; 
INSERT INTO table_new;
RENAME TABLE table TO table_old, table_new TO table; *atomic operation*
DROP TABLE table_old;

मैं PostgreSQL में इसे कैसे हासिल कर सकता हूं?

इस प्रश्न के प्रयोजनों के लिए, आप मान सकते हैं कि मैं विदेशी कुंजियों का उपयोग नहीं कर रहा हूँ।


आपको क्यों लगता है कि इसमें पंक्तियाँ सम्मिलित करते समय तालिका को पढ़ा नहीं जा सकता है? सभी सत्रों में ट्रंकट तालिका का तत्काल प्रभाव पड़ेगा; हालाँकि, आवेषण (यदि एक लेनदेन के अंदर किया जाता है जो उन सभी को लपेटता है, जैसा कि आपके छद्म कोड से पता चलता है) तब तक अन्य सत्रों में दिखाई नहीं देगा जब तक आप प्रतिबद्ध नहीं होते। अन्य सत्र तालिका से चयन करने में सक्षम होंगे, और जब तक आप प्रतिबद्ध नहीं होंगे तब तक एक खाली तालिका दिखाई देगी।
zgguy

2
@zgguy TRUNCATEकमांड टेबल पर एक AccessExclusive लॉक का अधिग्रहण करेगी, इसलिए कोई भी टेबल से तब तक नहीं पढ़ पाएगा जब तक कि लेन-देन शुरू नहीं हो जाता या वापस रोल नहीं किया जाता।
जोश कुपरशमिड्ट

2
यदि आप deleteइसके बजाय उपयोग करते हैं तो truncateयह धीमा होगा, लेकिन पाठकों को अवरुद्ध किए बिना। आपको हटाने के लिए कितनी पंक्तियों की आवश्यकता है?
a_horse_with_no_name

@a_horse_with_no_name आमतौर पर 200-300k पंक्तियों के बीच कई varchar कॉलम के साथ। की प्रतीक्षा समय DELETEऔर INSERTरास्ता बहुत लंबा हो जाएगा।
क्लार्क

जवाबों:


21

सही है, आप जो TRUNCATE TABLE कमांड कर रहे हैं "... प्रत्येक टेबल पर एक एसीसी एक्सेलसिव लॉक प्राप्त करता है " जिस पर आप काम करते हैं , इसलिए आपके द्वारा पोस्ट किए गए पहले एसक्यूएल ब्लॉक में, उस समय के बाद टेबल तक पहुंचने का प्रयास करने वाले किसी भी अन्य क्लाइंट को आपके INSERTखत्म होने तक अवरुद्ध कर दिया जाएगा। और तुम COMMIT

आप अपने MySQL के विशिष्ट कोड में उसी वर्कअराउंड का उपयोग कर सकते हैं; Postgres लगभग एक ही सिंटैक्स का समर्थन करता है और इसमें समान लॉकिंग व्यवहार होगा। अर्थात:

BEGIN;
-- You probably want to make sure that no one else is
-- INSERT / UPDATE / DELETE'ing from the original table, otherwise
-- those changes may be lost during this switchover process. One way
-- to do that would be via:
-- LOCK TABLE "table" IN SHARE ROW EXCLUSIVE mode;
CREATE TABLE "table_new" (LIKE "table");
INSERT INTO "table_new" ...;

-- The ALTER TABLE ... RENAME TO command takes an Access Exclusive lock on "table",
-- but these final few statements should be fast.
ALTER TABLE "table" RENAME TO "table_old";
ALTER TABLE "table_new" RENAME TO "table";
DROP TABLE "table_old";

COMMIT;

अतिरिक्त बोनस: Postgres वास्तव में MySQL के विपरीत, Transactional DDL का समर्थन करता है, इसलिए यदि आपको उपरोक्त लेनदेन को पूरा करने की आवश्यकता है, तो आप सुरक्षित रूप से ऐसा कर सकते हैं।


मैं इस पर कुछ परीक्षण करने जा रहा हूँ, आपके उत्तर के लिए धन्यवाद। यदि मैंने LOCK TABLEआपके द्वारा सुझाई गई विधि का उपयोग किया है , तो क्या मुझे इसे फिर से अनलॉक करने की आवश्यकता COMMITहोगी, या क्या यह खुद को अनलॉक करेगा?
क्लार्क

1
संपादित करें: इस दस्तावेज़ में निम्नलिखित क़ानून पाया गया : "कोई लॉक टेबल आदेश नहीं है; ताले हमेशा अंतिम छोर पर जारी किए जाते हैं।"
क्लार्क

2
यहाँ एक बात याद आ रही है कि सभी अड़चनें अभी भी जुड़ी हुई हैं_old
Intellix

@Intellix आप उस पर विस्तृत कर सकते हैं? क्या इसका मतलब है कि बाधाओं को पुरानी तालिका के अनुसार रखा गया है या वे केवल पुरानी तालिका से संबंधित हैं (इसका अर्थ है कि बाधाओं को प्रभावी रूप से हटा दिया गया है)?
मैरिक

तालिका निर्माण ( -- LOCK TABLE "table" IN ROW EXCLUSIVE mode;) से पहले की टिप्पणी किसी अद्यतन से बचाने के लिए / स्पेक्स के अनुसार स्रोत तालिका में सम्मिलित करने के लिए असुरक्षित लगती है। दो ROW EXCLUSIVEताले बिना किसी संघर्ष के हासिल किए जा सकते हैं (तालिका 13.2 को postgresql.org/docs/10/explicit-locking.html#LOCKING-TABLES में देखें )। डेटा अपडेट को रोकने के लिए आपको कम से कम SHAREलॉक की आवश्यकता होती है ।
पिल्लू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.