วิธีแก้ปัญหาสิทธิพิเศษเมื่อกู้คืนฐานข้อมูล PostgreSQL


105

ฉันทิ้งข้อมูลสำรองที่สะอาดและไม่มีเจ้าของสำหรับ Postgres Database ด้วยคำสั่ง

pg_dump sample_database -O -c -U

ต่อมาเมื่อฉันกู้คืนฐานข้อมูลด้วย

psql -d sample_database -U app_name

อย่างไรก็ตามฉันพบข้อผิดพลาดหลายประการซึ่งทำให้ฉันไม่สามารถกู้คืนข้อมูลได้:

ERROR:  must be owner of extension plpgsql
ERROR:  must be owner of schema public
ERROR:  schema "public" already exists
ERROR:  must be owner of schema public
CREATE EXTENSION
ERROR:  must be owner of extension plpgsql

ฉันขุดลงใน SQL ข้อความธรรมดาที่pg_dumpสร้างขึ้นและฉันพบว่ามันมี SQL

CREATE SCHEMA public;
COMMENT ON SCHEMA public IS 'standard public schema';
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';

ฉันคิดว่าสาเหตุเกิดจากผู้ใช้app_nameไม่มีสิทธิ์แก้ไขpublicสคีมาและplpgsql.

ฉันจะแก้ปัญหานี้ได้อย่างไร


5
ถ้าคุณไม่จำเป็นต้องplpgsqlแล้วก่อนที่คุณจะDROP EXTENSION plpgsql pg_dumpวิธีนี้ปลอดภัยกว่าการทำให้แอปของคุณเป็นผู้ใช้ขั้นสูงและสะดวกกว่าการเพิกเฉยต่อข้อผิดพลาด (ซึ่งจะระเบิดหากคุณใช้--single-transactionหรือ-v ON_ERROR_STOP=1) นี่เป็นปัญหาที่ทราบ [อธิบายโดยนักพัฒนา Postgres | postgresql.org/message-id/…แต่ไม่ได้รับการแก้ไขเมื่อ 9.3
Mark E.Haase

คำตอบ:


63

ในการแก้ปัญหาคุณต้องกำหนดสิทธิ์การเป็นเจ้าของที่เหมาะสม ลองทำตามด้านล่างนี้ซึ่งควรแก้ไขปัญหาที่เกี่ยวข้องกับการอนุญาตสำหรับผู้ใช้บางราย แต่ตามที่ระบุไว้ในความคิดเห็นสิ่งนี้ไม่ควรใช้ในการผลิต:

root@server:/var/log/postgresql# sudo -u postgres psql
psql (8.4.4)
Type "help" for help.

postgres=# \du
               List of roles
    Role name    | Attributes  | Member of
-----------------+-------------+-----------
 <user-name>    | Superuser   | {}
                 : Create DB
 postgres       | Superuser   | {}
                 : Create role
                 : Create DB

postgres=# alter role <user-name> superuser;
ALTER ROLE
postgres=#

ดังนั้นเชื่อมต่อกับฐานข้อมูลภายใต้บัญชี Superuser sudo -u postgres psqlและดำเนินการไฟล์ALTER ROLE <user-name> Superuser;คำสั่ง

โปรดทราบว่านี่ไม่ใช่ทางออกที่ดีที่สุดบนเซิร์ฟเวอร์โฮสติ้งแบบหลายไซต์ดังนั้นให้ดูที่การกำหนดบทบาทแต่ละบทบาทแทน: https://www.postgresql.org/docs/current/static/sql-set-role.htmlและhttps :


28
มีวิธีดำเนินการโดยไม่ต้องเป็น superuser ไหม
Travis Webb

17
"ต้องกำหนดสิทธิ์การเป็นเจ้าของที่เหมาะสม" และ "เปลี่ยนบทบาท <user-name> superuser" ไม่สอดคล้องกัน เจ้าของที่เหมาะสมจะหมายถึงว่าapp_userเป็นไม่ได้เป็นผู้ใช้ซุปเปอร์
Mark E.Haase

@mehaase โปรดอัปเดตคำตอบแทนการลงคะแนน
Daniel Sokolowski

5
IMHO นี่ไม่ใช่วิธีแก้ปัญหา แต่เป็นวิธีแก้ปัญหาที่ควรหลีกเลี่ยงในการผลิต
Dmytriy Voloshyn

6
เป็นคำแนะนำที่ไม่ดีในการทำให้ผู้ใช้ทั่วไปsuperuser
Evren Yurtesen

55

ผู้ใช้ AWS RDS หากคุณได้รับสิ่งนี้เป็นเพราะคุณไม่ใช่ superuser และตามเอกสารของ aws คุณไม่สามารถเป็นหนึ่งได้ ฉันพบว่าฉันต้องเพิกเฉยต่อข้อผิดพลาดเหล่านี้


5
ข้อผิดพลาดนี้ทำให้ฉันไม่สามารถกู้คืนได้สำเร็จ (AWS RDS pg_restore) มีเคล็ดลับในการละเว้นข้อผิดพลาดเหล่านี้หรือไม่?
avjaarsveld

ปล. ฉันไม่ได้ใช้ -e หรือ --exit-on-error สำหรับ pg_restore
avjaarsveld

7
ฉันได้พบว่าใน RDS ปัญหาคือไม่COMMENT ON EXTENSION CREATE EXTENSIONลบความคิดเห็นออกและคุณจะสบายดี
pkoch

@pkoch เช่นเดียวกับ Google Cloud Storage ความคิดเห็นเกี่ยวกับ EXTENSION เป็นปัญหาและไม่จำเป็น
Jaybeecave

25

สำหรับผู้ที่ใช้ Google Cloud Platform ข้อผิดพลาดใด ๆ จะหยุดกระบวนการนำเข้า โดยส่วนตัวแล้วฉันพบข้อผิดพลาดสองข้อที่แตกต่างกันขึ้นอยู่กับคำสั่ง pg_dump ที่ฉันออก:

1- The input is a PostgreSQL custom-format dump. Use the pg_restore command-line client to restore this dump to a database.

เกิดขึ้นเมื่อคุณพยายามถ่ายโอนข้อมูลฐานข้อมูลของคุณในรูปแบบข้อความที่ไม่ใช่ข้อความธรรมดา กล่าวคือเมื่อคำสั่งไม่มีพารามิเตอร์ -Fp หรือ --format = plain อย่างไรก็ตามหากคุณเพิ่มลงในคำสั่งคุณอาจพบข้อผิดพลาดต่อไปนี้:

2- SET SET SET SET SET SET CREATE EXTENSION ERROR: must be owner of extension plpgsql

นี่เป็นปัญหาที่ได้รับอนุญาตฉันได้รับไม่สามารถที่จะแก้ไขโดยใช้คำสั่งที่ระบุไว้ในเอกสาร GCPและเคล็ดลับจากหัวข้อในปัจจุบันนี้หรือคำแนะนำต่อไปนี้จากทีมงาน Google Postgres ที่นี่ ซึ่งแนะนำให้ใช้คำสั่งต่อไปนี้:

pg_dump -Fp --no-acl --no-owner -U myusername myDBName > mydump.sql

สิ่งเดียวที่ใช้เคล็ดลับในกรณีของฉันคือการแก้ไขไฟล์ดัมพ์ด้วยตนเองและแสดงความคิดเห็นคำสั่งทั้งหมดที่เกี่ยวข้องกับ plpgsql

ฉันหวังว่านี่จะช่วยวิญญาณที่พึ่งพา GCP ได้

อัปเดต:

มันง่ายกว่าที่จะถ่ายโอนไฟล์ที่แสดงความคิดเห็นส่วนขยายโดยเฉพาะอย่างยิ่งเนื่องจากการถ่ายโอนข้อมูลบางส่วนอาจมีขนาดใหญ่: pg_dump ... | grep -v -E '(CREATE\ EXTENSION|COMMENT\ ON)' > mydump.sql

ซึ่งสามารถ จำกัด ให้แคบลงเป็น plpgsql: pg_dump ... | grep -v -E '(CREATE\ EXTENSION\ IF\ NOT\ EXISTS\ plpgsql|COMMENT\ ON\ EXTENSION\ plpgsql)' > mydump.sql


1
ขณะนี้ GCP มีpg_dumpคำสั่งที่แน่นอนที่จะใช้ในเอกสารของพวกเขา:pg_dump -U [USERNAME] --format=plain --no-owner --no-acl [DATABASE_NAME] \ | sed -E 's/(DROP|CREATE|COMMENT ON) EXTENSION/-- \1 EXTENSION/g' > [SQL_FILE].sql
Rush

14

คุณสามารถเพิกเฉยต่อข้อความแสดงข้อผิดพลาดได้อย่างปลอดภัยในกรณีนี้ การไม่เพิ่มความคิดเห็นในสคีมาสาธารณะและการติดตั้ง plpgsql (ซึ่งควรติดตั้งแล้ว) จะไม่ทำให้เกิดปัญหาจริง

อย่างไรก็ตามหากคุณต้องการทำการติดตั้งใหม่ทั้งหมดคุณจะต้องมีผู้ใช้ที่มีสิทธิ์ที่เหมาะสม นั่นไม่ควรเป็นผู้ใช้แอปพลิเคชันของคุณทำงานเป็นประจำอย่างแน่นอน


12

คำตอบที่สั้นกว่า: ไม่ต้องสนใจ

โมดูลนี้เป็นส่วนหนึ่งของ Postgres ที่ประมวลผลภาษา SQL ข้อผิดพลาดมักจะปรากฏขึ้นเป็นส่วนหนึ่งของการคัดลอกฐานข้อมูลระยะไกลเช่นด้วย 'heroku pg: pull' มันไม่ได้เขียนทับตัวประมวลผล SQL ของคุณและเตือนคุณเกี่ยวกับสิ่งนั้น


11

ลองใช้-Lแฟล็กกับ pg_restore โดยระบุไฟล์ที่นำมาจากpg_dump -Fc

-L list-file --use-list = list-file

กู้คืนเฉพาะองค์ประกอบที่เก็บถาวรที่อยู่ในรายการไฟล์และกู้คืนตามลำดับที่ปรากฏในไฟล์ โปรดทราบว่าหากใช้สวิตช์การกรองเช่น -n หรือ -t กับ -L จะ จำกัด รายการที่เรียกคืนเพิ่มเติม

โดยปกติ list-file ถูกสร้างขึ้นโดยการแก้ไขเอาต์พุตของการดำเนินการ -l ก่อนหน้านี้ สามารถย้ายหรือลบเส้นได้และยังสามารถแสดงความคิดเห็นได้โดยวางอัฒภาค (;) ที่จุดเริ่มต้นของบรรทัด ดูตัวอย่างด้านล่าง

https://www.postgresql.org/docs/9.5/app-pgrestore.html

pg_dump -Fc -f pg.dump db_name
pg_restore -l pg.dump | grep -v 'COMMENT - EXTENSION' > pg_restore.list
pg_restore -L pg_restore.list pg.dump

ที่นี่คุณสามารถเห็นการผกผันเป็นจริงโดยแสดงเฉพาะความคิดเห็น:

pg_dump -Fc -f pg.dump db_name
pg_restore -l pg.dump | grep 'COMMENT - EXTENSION' > pg_restore_inverse.list
pg_restore -L pg_restore_inverse.list pg.dump
--
-- PostgreSQL database dump
--

-- Dumped from database version 9.4.15
-- Dumped by pg_dump version 9.5.14

SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';


--
-- PostgreSQL database dump complete
--

ฉันคิดว่าข้างต้นถูกต้อง แต่การไม่รวมความคิดเห็นสำหรับปลั๊กอินจะไม่มีผลกับการทำงานของแอปของคุณ
Andreas

นี่เป็นคำตอบที่ดีที่สุดอย่างแน่นอนไม่แน่ใจว่าทำไมจึงมีคำตอบต่ำกว่าสองคำตอบที่บอกว่าให้เพิกเฉย ...
Dylan

3

สำหรับผู้ที่ใช้AWSสิ่งCOMMENT ON EXTENSIONนี้เป็นไปได้ในฐานะผู้ใช้ขั้นสูงเท่านั้นและดังที่เราทราบในเอกสารอินสแตนซ์ RDS ได้รับการจัดการโดย Amazon ด้วยเหตุนี้เพื่อป้องกันไม่ให้คุณทำลายสิ่งต่างๆเช่นการจำลองแบบผู้ใช้ของคุณ - แม้แต่ผู้ใช้รูทที่คุณตั้งค่าเมื่อคุณสร้างอินสแตนซ์ - จะไม่มีสิทธิ์ superuser แบบเต็ม:

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

เมื่อคุณสร้างอินสแตนซ์ DB บัญชีผู้ใช้ระบบหลักที่คุณสร้างจะถูกกำหนดให้กับบทบาท rds_superuser บทบาท rds_superuser เป็นบทบาท Amazon RDS ที่กำหนดไว้ล่วงหน้าซึ่งคล้ายกับบทบาทผู้ใช้ขั้นสูงของ PostgreSQL (ตั้งชื่อตามปกติว่า postgres ในอินสแตนซ์ท้องถิ่น) แต่มีข้อ จำกัด บางประการ เช่นเดียวกับบทบาทผู้ใช้ขั้นสูงของ PostgreSQL บทบาท rds_superuser มีสิทธิพิเศษสูงสุดบนอินสแตนซ์ DB ของคุณและคุณไม่ควรกำหนดบทบาทนี้ให้กับผู้ใช้เว้นแต่ว่าพวกเขาต้องการการเข้าถึงอินสแตนซ์ DB มากที่สุด

ในการแก้ไขข้อผิดพลาดนี้เพียงแค่ใช้--เพื่อแสดงความคิดเห็นบรรทัดของ SQL ที่มีCOMMENT ON EXTENSION


2
หรือละเว้นความคิดเห็นเมื่อทิ้ง: pg_dump --no-comments.
Dmitrii I.

2

ใช้ผู้ใช้ postgres (ผู้ดูแลระบบ) เพื่อดัมพ์สคีมาสร้างขึ้นใหม่และให้สิทธิ์การใช้งานก่อนที่คุณจะทำการกู้คืน ในคำสั่งเดียว:

sudo -u postgres psql -c "DROP SCHEMA public CASCADE;
create SCHEMA public;
grant usage on schema public to public;
grant create on schema public to public;" myDBName

1

สำหรับฉันฉันกำลังตั้งค่าฐานข้อมูลด้วยpgAdminและดูเหมือนว่าการตั้งค่าเจ้าของในระหว่างการสร้างฐานข้อมูลนั้นไม่เพียงพอ ฉันต้องไปที่สคีมา 'สาธารณะ'และตั้งเจ้าของที่นั่นด้วย (เดิมคือ 'postgres')


0

สำหรับผู้ที่ จำกัด ปัญหาให้แคบลงในCOMMENT ONข้อความ (ตามคำตอบต่างๆด้านล่าง) และผู้ที่มี superuser เข้าถึงฐานข้อมูลต้นทางที่สร้างไฟล์ดัมพ์ทางออกที่ง่ายที่สุดคือป้องกันไม่ให้รวมความคิดเห็นลงในดัมพ์ ไฟล์ในตอนแรกโดยการลบออกจากฐานข้อมูลต้นทางที่ถูกทิ้ง ...

COMMENT ON EXTENSION postgis IS NULL;
COMMENT ON EXTENSION plpgsql IS NULL;
COMMENT ON SCHEMA public IS NULL;

การทิ้งในอนาคตจะไม่รวมCOMMENT ONงบ


1
การพัฒนาโลคัลใน Rails (ซึ่งจะสร้างไฟล์ดัมพ์ใหม่โดยอัตโนมัติเมื่อใดก็ตามที่มีการเรียกใช้การโอนย้ายสคีมา) โซลูชันนี้ช่วยให้ฉันสามารถรันrails db:resetกับอินสแตนซ์ Postgresql ของ AWS RDS โดยไม่ต้องลบบรรทัด COMMENT ON ออกจากไฟล์ดัมพ์ทุกครั้งที่เรียกใช้สคีมา การโยกย้าย.
Mark Schneider
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.