ฉันต้องเขียนสคริปต์ที่จะทิ้งฐานข้อมูล PostgreSQL อาจมีการเชื่อมต่อกับมันมากมาย แต่สคริปต์ควรละเว้นสิ่งนั้น
DROP DATABASE db_name
แบบสอบถามมาตรฐานไม่ทำงานเมื่อมีการเชื่อมต่อที่เปิดอยู่
ฉันจะแก้ปัญหาได้อย่างไร
ฉันต้องเขียนสคริปต์ที่จะทิ้งฐานข้อมูล PostgreSQL อาจมีการเชื่อมต่อกับมันมากมาย แต่สคริปต์ควรละเว้นสิ่งนั้น
DROP DATABASE db_name
แบบสอบถามมาตรฐานไม่ทำงานเมื่อมีการเชื่อมต่อที่เปิดอยู่
ฉันจะแก้ปัญหาได้อย่างไร
คำตอบ:
การดำเนินการนี้จะลดการเชื่อมต่อที่มีอยู่ยกเว้นสำหรับคุณ
ค้นหาpg_stat_activity
และรับค่า pid ที่คุณต้องการฆ่าแล้วออกค่าSELECT pg_terminate_backend(pid int)
เหล่านั้น
PostgreSQL 9.2 ขึ้นไป:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND pid <> pg_backend_pid();
PostgreSQL 9.1 และต่ำกว่า:
SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND procpid <> pg_backend_pid();
เมื่อคุณยกเลิกการเชื่อมต่อทุกคนคุณจะต้องตัดการเชื่อมต่อและออกคำสั่ง DATP DATABASE จากการเชื่อมต่อจากฐานข้อมูลอื่นหรือที่ไม่ใช่ที่คุณพยายามจะวาง
หมายเหตุ: การเปลี่ยนชื่อของคอลัมน์procpid
pid
ดูกระทู้รายการจดหมายนี้
; drop database TARGET_DB;
ทำงานได้ดีในกรณีของฉันเพื่อให้แน่ใจว่าฐานข้อมูลหายไปเมื่อเวลาที่เริ่มลองใหม่
dropdb --force
ฉันก็จะจ่ายเงินสำหรับ
ใน PostgreSQL 9.2 ขึ้นไปเพื่อยกเลิกการเชื่อมต่อทุกอย่างยกเว้นเซสชันของคุณจากฐานข้อมูลที่คุณเชื่อมต่อ:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid();
ในรุ่นเก่าก็เหมือนกันการเปลี่ยนแปลงเพียงเพื่อpid
procpid
หากต้องการยกเลิกการเชื่อมต่อจากฐานข้อมูลอื่นcurrent_database()
ให้เปลี่ยนเป็นชื่อของฐานข้อมูลที่คุณต้องการยกเลิกการเชื่อมต่อกับผู้ใช้
คุณอาจต้องการที่จะที่เหมาะสมจากผู้ใช้ฐานข้อมูลผู้ใช้ก่อนที่จะถอดมิฉะนั้นผู้ใช้ก็จะเก็บไว้ในการเชื่อมต่อใหม่และคุณจะไม่ได้รับโอกาสที่จะลดลงฐานข้อมูล ดูความคิดเห็นนี้และคำถามที่เกี่ยวข้องกับฉันจะแยกผู้ใช้รายอื่นออกจากฐานข้อมูลได้อย่างไรREVOKE
CONNECT
หากคุณต้องการยกเลิกการเชื่อมต่อผู้ใช้ที่ไม่ได้ใช้งานให้ดูคำถามนี้
คุณสามารถฆ่าการเชื่อมต่อทั้งหมดก่อนที่จะทิ้งฐานข้อมูลโดยใช้pg_terminate_backend(int)
ฟังก์ชั่น
คุณสามารถเรียกใช้แบ็กเอนด์ที่ทำงานอยู่ทั้งหมดโดยใช้มุมมองระบบ pg_stat_activity
ฉันไม่แน่ใจทั้งหมด แต่ต่อไปนี้อาจฆ่าเซสชันทั้งหมด:
select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'
แน่นอนคุณอาจไม่ได้เชื่อมต่อตัวเองกับฐานข้อมูลนั้น
ขึ้นอยู่กับรุ่น postgresql ของคุณคุณอาจพบข้อผิดพลาดซึ่งทำให้pg_stat_activity
ละเว้นการเชื่อมต่อที่ใช้งานอยู่จากผู้ใช้ที่ถูกทิ้ง การเชื่อมต่อเหล่านี้จะไม่ปรากฏใน pgAdminIII
หากคุณทำการทดสอบอัตโนมัติ (ซึ่งคุณสร้างผู้ใช้ด้วย) นี่อาจเป็นสถานการณ์ที่น่าจะเป็น
ในกรณีนี้คุณต้องเปลี่ยนกลับเป็นคำค้นหาเช่น:
SELECT pg_terminate_backend(procpid)
FROM pg_stat_get_activity(NULL::integer)
WHERE datid=(SELECT oid from pg_database where datname = 'your_database');
หมายเหตุ: ใน 9.2+ คุณจะมีการเปลี่ยนแปลงไปprocpid
pid
procpid
เป็นpid
ข้อมูลโค้ดนี้ทำงานบน 9.3
ฉันสังเกตเห็นว่า postgres 9.2 ตอนนี้เรียกว่าคอลัมน์ pid แทนที่จะเป็น procpid
ฉันมักจะเรียกมันจากเปลือก:
#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
where="where pg_stat_activity.datname = '$1'"
echo "killing all connections to database '$1'"
else
echo "killing all connections to database"
fi
cat <<-EOF | psql -U postgres -d postgres
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF
หวังว่าจะเป็นประโยชน์ ขอบคุณ @JustBob สำหรับ sql
ฉันเพิ่งเริ่มบริการใน Ubuntu เพื่อตัดการเชื่อมต่อลูกค้า
sudo service postgresql stop
sudo service postgresql start
psql
DROP DATABASE DB_NAME;
ในพรอมต์คำสั่ง Linux ฉันจะหยุดกระบวนการ postgresql ทั้งหมดที่กำลังทำงานอยู่โดยการผูกคำสั่งนี้ sudo /etc/init.d/postgresql รีสตาร์ททั้งหมด
พิมพ์คำสั่ง bgเพื่อตรวจสอบว่ากระบวนการ postgresql อื่นยังคงทำงานอยู่หรือไม่
จากนั้นตามด้วยdropdb dbnameเพื่อวางฐานข้อมูล
sudo /etc/init.d/postgresql restart
bg
dropdb dbname
สิ่งนี้ใช้ได้กับฉันในพรอมต์คำสั่ง linux
PostgreSQL 9.2 ขึ้นไป:
SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'
นี่คือแฮ็คของฉัน ... = D
# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"
# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"
# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"
ฉันใส่คำตอบนี้เพราะรวมคำสั่ง (ด้านบน) เพื่อบล็อกการเชื่อมต่อใหม่และเพราะความพยายามใด ๆ กับคำสั่ง ...
REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;
... ไม่ทำงานเพื่อบล็อกการเชื่อมต่อใหม่!
ขอบคุณ @araqnid @GoatWalker! = D
PostgreSQL 13 ที่กำลังจะจัดขึ้นจะแนะนำFORCE
ตัวเลือก
DROP DATABASEลดลงฐานข้อมูล ... นอกจากนี้ถ้าใครก็ตามที่มีการเชื่อมต่อกับฐานข้อมูลเป้าหมายที่คำสั่งนี้จะล้มเหลวจนกว่าคุณจะใช้FORCEตัวเลือกที่อธิบายไว้ด้านล่าง
บังคับ
พยายามยกเลิกการเชื่อมต่อที่มีอยู่ทั้งหมดไปยังฐานข้อมูลเป้าหมาย ไม่สิ้นสุดหากธุรกรรมที่เตรียมไว้, ช่องการจำลองแบบโลจิคัลที่ใช้งานอยู่หรือการสมัครสมาชิกมีอยู่ในฐานข้อมูลเป้าหมาย
DROP DATABASE db_name WITH (FORCE);
ในกรณีของฉันฉันต้องดำเนินการคำสั่งเพื่อวางการเชื่อมต่อทั้งหมดรวมถึงการเชื่อมต่อผู้ดูแลระบบที่ใช้งานของฉัน
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
ซึ่งยุติการเชื่อมต่อทั้งหมดและแสดงข้อความ "ผิดพลาด" ร้ายแรงถึงฉัน:
FATAL: terminating connection due to administrator command SQL state: 57P01
หลังจากนั้นเป็นไปได้ที่จะลบฐานข้อมูล
ไม่มีอะไรทำงานให้ฉันยกเว้นฉันเข้าสู่ระบบโดยใช้ pgAdmin4 และบนแดชบอร์ดฉันยกเลิกการเชื่อมต่อการเชื่อมต่อทั้งหมดยกเว้น pgAdmin4 และจากนั้นก็สามารถเปลี่ยนชื่อโดยเลียขวาในฐานข้อมูลและคุณสมบัติและพิมพ์ชื่อใหม่