ডাম্প পুনরুদ্ধার করার সময় সমস্ত সীমাবদ্ধতা এবং টেবিল চেকগুলি অক্ষম করুন


19

আমি আমার পোস্টগ্রিজ এসকিউএল ডাটাবেসের সাথে একটি ডাম্প পেয়েছি:

pg_dump -U user-name -d db-name -f dumpfile

যা আমি এর সাথে অন্য একটি ডাটাবেসে পুনরুদ্ধার করতে এগিয়ে চলেছি:

psql X -U postgres  -d db-name-b -f dumpfile

আমার সমস্যাটি হ'ল ডাটাবেসে রেফারেনশিয়াল সীমাবদ্ধতা, চেক এবং ট্রিগার থাকে এবং এর মধ্যে কিছু (এটি বিশেষত চেকগুলি মনে হয়) পুনরুদ্ধারের সময় ব্যর্থ হয় যেহেতু তথ্যগুলি ক্রমযুক্তভাবে লোড না করা হয় যা এই চেকগুলিকে সম্মানিত করতে পারে। উদাহরণস্বরূপ, কোনও সারণীতে একটি সারি সন্নিবেশ করানো CHECKএমন কোনও plpgsqlফাংশনের সাথে কল করে যা শর্তটি অন্য কোনও সম্পর্কযুক্ত টেবিলের মধ্যে রয়েছে কিনা তা পরীক্ষা করে with যদি পূর্ববর্তী টেবিলটি psqlপূর্বের আগে লোড না করা হয় তবে একটি ত্রুটি ঘটে।

নিম্নলিখিতটি এমন একটি এসএসসিসিই যা এমন ডেটাবেস তৈরি করে যা একবার ডাম্প করে pg_dumpপুনরুদ্ধার করা যায় না:

CREATE OR REPLACE FUNCTION fail_if_b_empty () RETURNS BOOLEAN AS $$
    SELECT EXISTS (SELECT 1 FROM b)
$$ LANGUAGE SQL;

CREATE TABLE IF NOT EXISTS a (
     i              INTEGER                    NOT NULL
);

INSERT INTO a(i) VALUES (0),(1);
CREATE TABLE IF NOT EXISTS b (
    i  INTEGER NOT NULL
);
INSERT INTO b(i) VALUES (0);

ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty());

ডাম্প পুনরুদ্ধারের সময় এমন সমস্ত প্রতিবন্ধকতাগুলি (কমান্ড লাইন থেকে) অক্ষম করার এবং পরে আবার তাদের সক্ষম করার কোনও উপায় আছে কি? আমি পোস্টগ্রেএসকিউএল 9.1 চালাচ্ছি।


আমি হতাশ করছি, আমি যতদূর জানি সেখানে নেই -Xএবং -dজন্য বিকল্পগুলি pg_dumppg_dumpএকটি ডাম্প যে উত্পাদন করে হয় একটি খালি ডিবি মধ্যে restorable।
dezso

1
@ ডেসো ঠিক আছে, এগুলি টাইপস ছিল, আমি প্রশ্নটি আপডেট করেছি। দুঃখের সাথে ডাম্পটি, যে কারণে আমি উদ্ধৃত করছি তার কারণে খালি ডিবিতে প্রশ্রয় দেওয়া যায় না
মার্কাস জুনিয়াস ব্রুটাস

প্রশ্নটি আপনার পোস্টগ্রাসের সংস্করণটির খারাপভাবে দরকার। এটি আমার দিকে নির্দেশ না করে এটি সুস্পষ্ট হওয়া উচিত।
এরউইন ব্র্যান্ডসটেটার

@ এরউইন ব্র্যান্ডসেটেটার আমি একই সমস্যাটি 9.6-এ পুনরুত্পাদন করতে পারি, অন্য উদাহরণের জন্য বাগ.ডিবিয়ান.আরবিআইএন /সিগি -বিন / বুগেরপোর্টসি.কি? বুগ=859033 দেখুন (আরও বাস্তব-বিশ্বের, কিছুটা বড়, এমডাব্লুইই)
মিরাবিলোস

1
@ মিরাবিলোস: আমি বলব: আপনি যদি এমন কোনও ফাংশন ব্যবহার করেন যা অন্য সারণিকে কোনও CHECKবাধা হিসাবে উল্লেখ করে, তবে সমস্ত গ্যারান্টি খালি করা হবে, কারণ এটি আনুষ্ঠানিকভাবে সমর্থিত নয়, কেবল সহনীয়। তবে CHECKসীমাবদ্ধতা ঘোষণা NOT VALIDকরা আমার পক্ষে এটি সর্বদাই কাজ করে। এমন কোনও কোণার ক্ষেত্রেও থাকতে পারে যা আমি কখনও স্পর্শ করি নি ...
এরউইন ব্র্যান্ডসেটেটার

উত্তর:


17

সুতরাং আপনি একটি CHECKসীমাবদ্ধতার মধ্যে অন্যান্য সারণী সন্ধান করুন ।

CHECKসীমাবদ্ধতাগুলি IMMUTABLEচেক চালানোর কথা । একবারে সারির জন্য যা ঠিক আছে তা যে কোনও সময় ঠিক আছে । CHECKএসকিউএল স্ট্যান্ডার্ডে এইভাবে বাধাগুলি সংজ্ঞায়িত করা হয়। এই সীমাবদ্ধতার কারণও ( প্রতি ডকুমেন্টেশন ):

বর্তমানে, CHECKএক্সপ্রেশনগুলিতে সাব-কোয়েরি থাকতে পারে না বা বর্তমান সারিটির কলামগুলি ব্যতীত ভেরিয়েবলগুলি উল্লেখ করা যায় না।

এখন, CHECKসীমাবদ্ধতার মধ্যে অভিব্যক্তিগুলি ফাংশন, এমনকি ব্যবহারকারী-সংজ্ঞায়িত ফাংশনগুলি ব্যবহার করার অনুমতি দেয়। এগুলি IMMUTABLEফাংশনে সীমাবদ্ধ হওয়া উচিত , তবে পোস্টগ্রিস বর্তমানে এটি প্রয়োগ করে না। পিএসএসকিএল-হ্যাকার সম্পর্কিত এই সম্পর্কিত আলোচনা অনুসারে , এর একটি কারণ হ'ল বর্তমান সময়ের রেফারেন্সগুলি মঞ্জুর করা যা IMMUTABLEপ্রকৃতির দ্বারা নয় ।

তবে আপনি অন্য সারণির সারি সন্ধান করছেন যা সম্পূর্ণরূপে লঙ্ঘন করে কীভাবে CHECKকাজ করার মতো প্রতিবন্ধকতা রয়েছে। আমি pg_dumpএই জন্য সরবরাহ করতে ব্যর্থ যে অবাক হয় না ।

আপনার চেকটিকে অন্য টেবিলে একটি ট্রিগারে স্থানান্তর করুন (যা সঠিক সরঞ্জাম), এবং এটি পোস্টগ্রাসের আধুনিক সংস্করণগুলির সাথে কাজ করা উচিত।

PostgreSQL 9.2 বা তারপরে

উপরের পোস্টগ্রিসের যে কোনও সংস্করণের জন্য সত্য, আপনার পরিস্থিতিটি সহায়তা করতে পোস্টগ্রিস 9.2 এর সাথে বেশ কয়েকটি সরঞ্জাম প্রবর্তিত হয়েছে:

pg_dump বিকল্প --exclude-table-data

একটি সহজ সমাধান হ'ল লঙ্ঘনকারী সারণীর জন্য ডেটা ছাড়াই ডিবি ডাম্প করা:

--exclude-table-data=my_schema.my_tbl

তারপরে ডাম্পের শেষে এই টেবিলের জন্য কেবলমাত্র ডেটা যুক্ত করুন:

--data-only --table=my_schema.my_tbl

তবে একই টেবিলে অন্যান্য সীমাবদ্ধতার জটিলতা দেখা দিতে পারে। এর চেয়ে আরও ভাল সমাধান রয়েছে :

NOT VALID

নেই NOT VALIDসীমাবদ্ধতার জন্য পরিবর্তক। কেবলমাত্র v9.1 এফকে বাধা জন্য উপলব্ধ, তবে এটি CHECK9.2-এ সীমাবদ্ধতায় প্রসারিত হয়েছিল । প্রতি ডকুমেন্টেশন:

সীমাবদ্ধতা চিহ্নিত করা থাকলে NOT VALID, সারণীর সমস্ত সারি সীমাবদ্ধতা পূরণ করে তা যাচাই করার জন্য সম্ভাব্য দীর্ঘ-প্রাথমিক প্রাথমিক চেকটি বাদ দেওয়া হয়েছে। পরবর্তী সন্নিবেশ বা আপডেটের বিরুদ্ধে এখনও এই সীমাবদ্ধতা প্রয়োগ করা হবে [...]

একটি সাধারণ পোস্টগ্রিস ডাম্প ফাইলের মধ্যে তিনটি "বিভাগ" রয়েছে:

  • pre_data
  • data
  • post-data

পোস্টগ্রিস ৯.২ এছাড়াও বিভাগগুলি পৃথকভাবে ডাম্প করার জন্য একটি বিকল্প চালু করেছিল -- section=sectionname, তবে এটি সমস্যাটির সাথে হাত দিচ্ছে না।

আকর্ষণীয় হয়ে ওঠে এখানে। প্রতি ডকুমেন্টেশন:

পোস্ট-ডেটা আইটেমগুলির মধ্যে সূচীগুলির সংজ্ঞা, ট্রিগার, নিয়ম এবং বৈধতাযুক্ত চেক সীমাবদ্ধতা ব্যতীত বাধা অন্তর্ভুক্ত থাকে । প্রাক ডেটা আইটেমগুলিতে অন্যান্য সমস্ত ডেটা সংজ্ঞা আইটেম অন্তর্ভুক্ত।

বোল্ড জোর আমার।
আপনি আপত্তিজনক CHECKসীমাবদ্ধতায় পরিবর্তন করতে পারেন NOT VALID, যা সীমাবদ্ধতাটিকে post-dataবিভাগে সরিয়ে দেয় । ড্রপ এবং পুনরায় তৈরি করুন:

ALTER TABLE a DROP CONSTRAINT a_constr_1;
ALTER TABLE a ADD  CONSTRAINT a_constr_1 CHECK (fail_if_b_empty()) NOT VALID;

এটা আপনার সমস্যা সমাধান করবে. এমনকি আপনি সেই স্থানে বাধাও ছেড়ে দিতে পারেন , যেহেতু এটি আসলে কী করে তা আরও ভালভাবে প্রতিফলিত করে: নতুন সারি পরীক্ষা করুন, তবে বিদ্যমান ডেটার জন্য কোনও গ্যারান্টি দেবেন না। NOT VALIDচেক সীমাবদ্ধতায় কোনও ভুল নেই। আপনি যদি পছন্দ করেন তবে পরে এটি যাচাই করতে পারবেন:

ALTER TABLE a VALIDATE CONSTRAINT a_constr_1;

তবে তারপরে আপনি স্থিতি ফিরে এসেছেন।


আমি একটি এসএসসিসিই দিয়ে প্রশ্নটি সমৃদ্ধ করেছি যা কোনও ডাটাবেস দেখায় যা পুনরুদ্ধার করা যায় না। আমি যা বলছি তা পেয়েছি, তবে আমার এসএসসিসিইতে যে সমস্যাযুক্ত পরিস্থিতি আমি দেখছি তা কেন চেকের পরিবর্তে ট্রিগার দিয়ে পুনরুত্পাদন করা যায় না তা আমি দেখতে পাচ্ছি না।
মার্কাস জুনিয়াস ব্রুটাস

1
@ মার্কাসজুনিয়াস ব্রুটাস: কারণ সৃষ্টির টেবিলটিতে ইতিমধ্যে থাকা সমস্ত সারিগুলির জন্য চেক সীমাবদ্ধতাগুলি মূল্যায়ন করা হয়, তবে ট্রিগারগুলি কেবল নির্ধারিত ইভেন্টগুলিতে চালিত হয়।
এরউইন ব্র্যান্ডসটেটার

আমি ট্রিগারগুলি ব্যবহার করে সঠিক স্কিমা যুক্তি পুনরুত্পাদন করেছি। ট্রিগারগুলি ব্যবহার করে, পুনরুদ্ধারটি সত্যই সফল হয় তবে এটি pg_dumpডাম্প ফাইলের শেষে ট্রিগারগুলি যুক্ত করার কারণে ঘটেছিল এবং এটি কমান্ডের CHECKঅংশ হিসাবে এস তৈরি করে CREATE TABLE। সুতরাং pg_dumpসরঞ্জামটি যদি অন্যরকম পদ্ধতির ব্যবহার করে তবে পুনরুদ্ধারটিও চেকের ক্ষেত্রে সফল হতে পারে । আমি যদি ট্রিগার ব্যবহার করি তবে আমার ডিডিএল কেন ঠিক আছে তা দেখতে ব্যর্থ হয়েছি তবে আমি যদি চেক ব্যবহার করি তবে ঠিক একই যুক্তি উভয় ক্ষেত্রেই প্রয়োগ করা হয়েছে (আপনি আমার নিজের উত্তরে ট্রিগার ব্যবহার করে স্ক্রিপ্টের সংস্করণটি দেখতে পারেন)।
মার্কাস জুনিয়াস ব্রুটাস

1
@ মার্কাসজুনিয়াস ব্রুটাস: যদি আপনি মনে করেন যে pg_dumpচেক সীমাবদ্ধতার জন্য আলাদা আলাদা ডিডিএল তৈরি করা উচিত (উদাহরণস্বরূপ এগুলি সবগুলি যুক্ত করে) আপনার পোস্টের বর্ধিতকরণের অনুরোধ হিসাবে মেলিং তালিকায় পোস্ট করতে হবে। তবে আমি এরউইনের সাথে একমত যে আপনি যা কিছু ডিজাইন করেননি তার জন্য আপনি চেক সীমাবদ্ধতার ভুল ব্যবহার করছেন। সুতরাং আমি আশা করি না যে পরিবর্তনের অনুরোধটি অদূর ভবিষ্যতে কার্যকর হবে। বিটিডব্লিউ: আপনার এসএসসিসিই দুটি টেবিলের মধ্যে একটি বিদেশী কী ব্যবহার করে আরও ভাল মডেল করা হবে।
a_horse_with_no_name

@ মার্কাসজুনিয়াস ব্রুটাস: পোস্টগ্রিস ৯.২ বা তার পরে এর সমাধান রয়েছে। এজন্য আপনার পোস্টগ্রিসের সংস্করণটি গুরুত্বপূর্ণ। হয়তো আপগ্রেড করা আপনার পক্ষে একটি বিকল্প? পোস্টগ্রিস 9.1 যাইহোক বয়স বাড়ছে ...
এরউইন ব্র্যান্ডসেটেটার

2

দেখে মনে হচ্ছে pg_dumpএটি ডাম্প তৈরির কারণেই। আসল ডাম্পের দিকে তাকিয়ে আমি দেখতে পেলাম যে কমান্ডের CHECKঅংশ সিনট্যাক্স ব্যবহার করে ডাম্প ফাইলে বাধা উপস্থিত ছিল CREATE TABLE:

CREATE TABLE a (
    i integer NOT NULL,
    CONSTRAINT a_constr_1 CHECK (fail_if_b_empty())
);      

এটি ডাটাবেস পুনরুদ্ধারের উপর ব্যর্থতা তৈরি করে কারণ টেবিল aবা সারণিতে bযে কোনও ডেটা থাকার আগে চেকটি স্থাপন করা হয় । তবে, ডাম্প ফাইলটি সম্পাদনা করা হয় এবং এর CHECKপরিবর্তে ডাম্প ফাইলের শেষে নিম্নলিখিত সিনট্যাক্স ব্যবহার করে যুক্ত করা হয়:

ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty()); 

... তাহলে পুনরুদ্ধারে কোনও সমস্যা নেই।

TRIGGERনীচের স্ক্রিপ্টের মতো ব্যবহার করে সঠিক একই যুক্তি প্রয়োগ করা যেতে পারে :

CREATE OR REPLACE FUNCTION fail_if_b_empty (
    ) RETURNS BOOLEAN AS $$
    SELECT EXISTS (SELECT 1 FROM b)
$$ LANGUAGE SQL;

DROP TABLE IF EXISTS a;

CREATE TABLE IF NOT EXISTS a (
    i   INTEGER   NOT NULL
);

INSERT INTO a(i) VALUES (0),(1);

CREATE TABLE IF NOT EXISTS b (
    i  INTEGER NOT NULL
);

INSERT INTO b(i) VALUES (0);

CREATE TRIGGER tr1 AFTER INSERT OR UPDATE ON a
FOR EACH ROW
EXECUTE PROCEDURE fail_if_b_empty();  

তবে এই ক্ষেত্রে, pg_dumpডাম্প ফাইলের শেষে ট্রিগার তৈরি করে (ডিফল্টরূপে) (এবং CREATE TABLEকোনও চেকের ক্ষেত্রে বিবৃতিতে নয় ) এবং তাই পুনরুদ্ধার সফল হয়।


আপনার উদাহরণে কোনও ট্রিগার দেখতে পাবেন না
স্যাম ওয়াটকিন্স

1
@ সামা ওয়াটকিন্স অনুলিপি-পেস্ট করুন
মার্কাস জুনিয়াস ব্রুটাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.