यदि कोई सक्रिय कनेक्शन हैं तो पोस्टग्रेएसक्यूएल डेटाबेस को कैसे छोड़ें?


648

मुझे एक स्क्रिप्ट लिखने की ज़रूरत है जो एक PostgreSQL डेटाबेस को छोड़ देगी। इसके बहुत सारे कनेक्शन हो सकते हैं, लेकिन स्क्रिप्ट को इसे अनदेखा करना चाहिए।

DROP DATABASE db_nameखुले कनेक्शन होने पर मानक क्वेरी काम नहीं करती है।

मैं समस्या को कैसे हल कर सकता हूँ!


1
आप PostgreSQL के किस संस्करण पर हैं?
कुबेरचुन

1
समस्या: जब तक आप डेटाबेस से जुड़े सत्रों को मार सकते हैं, वे इतनी जल्दी फिर से जुड़ सकते हैं कि आप अभी भी डेटाबेस को नहीं छोड़ सकते। खुशी से यह पोस्ट दिखाता है कि नए कनेक्शन को कैसे लॉक किया जाए, इसलिए आप वर्तमान कनेक्शन को मार सकते हैं और डेटाबेस को योजना के अनुसार छोड़ सकते हैं: dba.stackexchange.com/questions/11893/…
अधिकतम मर्फी

1
मुझे यह जवाब dba.stackexchange पर बहुत मददगार लगा। dba.stackexchange.com/a/11895/163539 - अभी तक पर्याप्त व्याख्यात्मक है।
hlongmore

जवाबों:


1093

यह आपके लिए छोड़कर मौजूदा कनेक्शन को छोड़ देगा:

क्वेरी pg_stat_activityऔर उन पीड मूल्यों को प्राप्त करें जिन्हें आप मारना चाहते हैं, फिर 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();

एक बार जब आप सभी को डिस्कनेक्ट कर देते हैं, तो आपको डिस्कनेक्ट करना होगा और डीआरओपी डेटाबेस कमांड को दूसरे डेटाबेस उर्फ ​​से कनेक्शन से जारी करना होगा, जिसे आपका ड्रॉप करने का प्रयास नहीं किया गया है।

procpidस्तंभ का नाम बदलने पर ध्यान दें pidयह मेलिंग सूची धागा देखें ।


11
और हां, यह सुनिश्चित करें कि एक db कनेक्शन से जो 'TARGET_DB' के लिए कनेक्शन नहीं है, अन्यथा आपको 'ERROR' मिलता है। एक 'पोस्टग्रैज' कनेक्शन अच्छी तरह से काम करता है।
रोब

3
वास्तव में यह एक-एक करके ग्राहकों को डिस्कनेक्ट करेगा, और यदि आप ग्राहक सूची के बीच में हैं तो इसे भी काट दिया जाएगा। नतीजतन, कुछ कनेक्शन जीवित रहेंगे। तो, सही जवाब क्रेग रिंगर (नीचे देखें) है। चयन pg_terminate_backend (pg_stat_activity.pid) से pg_stat_activity WHERE datname = current_database () और pg_stat_activity.pid <> pg_backend_pid ();
एंड्रयू सेलिवानोव

1
जब वे अपने वर्तमान लेनदेन के साथ समाप्त कर लेते हैं और फिर प्रश्न में तालिका (ओं) को छोड़ देते हैं तो मैं कनेक्शन कैसे काट सकता हूं?
पॉलकॉन

5
मेरे मामले में ग्राहक जल्दी से जुड़ जाएंगे, इसलिए यह ; drop database TARGET_DB;सुनिश्चित करने के लिए मेरे मामले में अच्छी तरह से काम करने से पहले कि यह सुनिश्चित करने के लिए db चला गया था कि चीजें फिर से शुरू हो रही थीं।
Mat Schaffer

1
मैं भी एक के लिए पैसे का भुगतान करेगा dropdb --force
टॉरस्ट ब्रोंगर

125

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()उस डेटाबेस के नाम को बदलें जिसे आप उपयोगकर्ताओं से डिस्कनेक्ट करना चाहते हैं।

आप कर सकते हैं , उन डिस्कनेक्ट करने से पहले डेटाबेस के उपयोगकर्ताओं से सही नहीं तो उन सिर्फ पुनः कनेक्ट हो पर रखेंगे और आप डीबी ड्रॉप करने का मौका कभी नहीं मिलेगा। इस टिप्पणी और इसके साथ जुड़े प्रश्न को देखें , मैं डेटाबेस से अन्य सभी उपयोगकर्ताओं को कैसे अलग कर सकता हूंREVOKECONNECT

यदि आप केवल निष्क्रिय उपयोगकर्ताओं को डिस्कनेक्ट करना चाहते हैं, तो यह प्रश्न देखें ।


3
चयन pg_terminate_backend (pg_stat_activity.pid) से pg_stat_activity WHERE datname = current_database () और pg_stat_activity.pid <> pg_backend_pid ();
एंड्रयू सेलिवानोव

26

आप pg_terminate_backend(int)फ़ंक्शन का उपयोग करके डेटाबेस को छोड़ने से पहले सभी कनेक्शनों को मार सकते हैं ।

आप सिस्टम व्यू का उपयोग करके सभी रनिंग बैकएंड प्राप्त कर सकते हैं pg_stat_activity

मुझे पूरा यकीन नहीं है, लेकिन निम्नलिखित शायद सभी सत्रों को मार देंगे:

select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'

बेशक आप खुद को उस डेटाबेस से नहीं जोड़ सकते हैं


19

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


1
Ths वह है जो मैं ढूंढ रहा था, लेकिन (9.2 और उससे आगे के लिए) आपको pg_stat_activity के संदर्भ को हटाना होगा और pid के लिए procpid बदलना होगा।
एमडीआर

2
इस स्निपेट procpidको बदलने के बाद pid9.3 पर काम करता है।
जेबी

pg_stat_activity को हटाए बिना भी? मुझे 9.2
एमडीआर

ठीक। अब मैं समझ गया, वह एक टाइपो था। धन्यवाद!
जेबी

2
9.3 से और ऊपर का चयन करें
शॉन वडर

17

मैंने देखा कि 9.2 पोस्टपार्ट करता है, अब कॉलपिड को कॉलपिड के बजाय कॉल करता है।

मैं इसे शेल से बुलाना चाहता हूं:

#!/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

आशा है कि सहायक है। Sql के लिए @Justbus को धन्यवाद।


15

मैं सिर्फ कनेक्टेड क्लाइंट को डिस्कनेक्ट करने के लिए उबंटू में सेवा को फिर से शुरू करता हूं।

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;

10

लिनक्स कमांड प्रॉम्प्ट में, मैं सबसे पहले इस कमांड sudo /etc/init.d/postgresql पुनरारंभ को बांधकर चलने वाली सभी पोस्टग्रेजल प्रक्रियाओं को रोक दूंगा

यह जाँचने के लिए कि अन्य पोस्टग्रैसक्ल प्रक्रियाएँ अभी भी चल रही हैं , कमांड बीजी टाइप करें

फिर ड्रॉपडब dbname द्वारा डेटाबेस को छोड़ने के लिए

sudo /etc/init.d/postgresql restart
bg
dropdb dbname

यह मेरे लिए लिनक्स कमांड प्रॉम्प्ट पर काम करता है


6
यह अच्छा नहीं है यदि आपके पास कई डेटाबेस हैं और केवल एक ही डीबी के लिए कनेक्शन छोड़ना चाहते हैं। यह सभी कनेक्शनों को मार देगा। यह थोड़ा "स्लेज हैमर-वाई" है।
निक

2
@ सच है, लेकिन याद रखें कि हम सभी कनेक्शनों को फिर से शुरू कर रहे हैं और उन्हें पूरी तरह से रोक रहे हैं
मौरिस एल्गु


8

यहाँ मेरा हैक है ... = डी

# 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

https://stackoverflow.com/a/3185413/3223785


5

आगामी PostgreSQL 13 FORCEविकल्प पेश करेगा ।

ड्रॉपडाउन

DROP DATABASE एक डेटाबेस को छोड़ देता है ... इसके अलावा, यदि कोई अन्य व्यक्ति लक्ष्य डेटाबेस से जुड़ा है, तो यह कमांड तब तक विफल रहेगा जब तक कि आप नीचे वर्णित बल विकल्प का उपयोग नहीं करते हैं।

बल

लक्ष्य डेटाबेस के सभी मौजूदा कनेक्शन को समाप्त करने का प्रयास करें। यदि तैयार लेनदेन, सक्रिय तार्किक प्रतिकृति स्लॉट या सदस्यता लक्ष्य डेटाबेस में मौजूद हैं तो यह समाप्त नहीं होता है।

DROP DATABASE db_name WITH (FORCE);

0

मेरे मामले में मुझे अपने सक्रिय व्यवस्थापक कनेक्शन सहित सभी कनेक्शनों को छोड़ने के लिए एक कमांड निष्पादित करना पड़ा

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

इसके बाद डेटाबेस को गिराना संभव हो गया


0

सिवाय मेरे लिए कुछ भी काम नहीं किया, मैंने pgAdmin4 का उपयोग करके लॉगिन किया और डैशबोर्ड पर मैंने pgAdmin4 को छोड़कर सभी कनेक्शन काट दिए और फिर डेटाबेस और गुणों पर राइट लिक द्वारा नाम बदलने में सक्षम था और नया नाम टाइप किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.