যদি কোনও পোস্টগ্রিজ এসকিউএল ডাটাবেস সক্রিয় সংযোগ থাকে তবে কীভাবে তা ফেলে রাখবেন?


648

আমাকে এমন একটি স্ক্রিপ্ট লিখতে হবে যা একটি পোস্টগ্রিজ এসকিউএল ডাটাবেস ছাড়বে। এটির সাথে প্রচুর সংযোগ থাকতে পারে তবে স্ক্রিপ্টের এটিকে উপেক্ষা করা উচিত।

DROP DATABASE db_nameযখন খোলা সংযোগ রয়েছে তখন স্ট্যান্ডার্ড ক্যোয়ারি কাজ করে না।

আমি কীভাবে সমস্যার সমাধান করতে পারি?


1
আপনি পোস্টগ্রিজএসকিউএল এর কোন সংস্করণে আছেন?
কুবেরচাঁন

1
সমস্যা: আপনি ডাটাবেসের সাথে সংযুক্ত অধিবেশনগুলিকে মেরে ফেলতে পারেন, তারা এত তাড়াতাড়ি পুনরায় সংযোগ করতে পারে যাতে আপনি এখনও ডাটাবেসটি ফেলে দিতে পারবেন না। সুখের সাথে এই পোস্টটি নতুন সংযোগগুলি কীভাবে লক আউট করবেন তা দেখায়, সুতরাং আপনি তারপরে বর্তমান সংযোগগুলি মেরে ফেলতে পারেন এবং পরিকল্পনা অনুসারে ডাটাবেসটি ফেলে দিতে পারেন: dba.stackexchange.com/questions/11893/…
ম্যাক্স মারফি

1
আমি dba.stackexchange.com/a/11895/163539 - সংক্ষিপ্ত এখনও যথেষ্ট ব্যাখ্যাযোগ্য হিসাবে dba.stackexchange এ এই উত্তরটি পেয়েছি ।
hlongmore

উত্তর:


1092

এটি আপনার ব্যতীত বিদ্যমান সংযোগগুলি ফেলে দেবে:

pg_stat_activityআপনি যে পিডের মানগুলি মেরে ফেলতে চান তার অনুসন্ধান করুন এবং তারপরে SELECT pg_terminate_backend(pid int)তাদের কাছে ইস্যু করুন।

পোস্টগ্রিএসকিউএল 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();

পোস্টগ্র্যাস এসকিউএল 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();

একবার আপনি সকলকে সংযোগ বিচ্ছিন্ন করে ফেললে আপনাকে অন্য সংখ্যক ডাটাবেস থেকে একটি সংযোগ থেকে ড্রপ DATABASE কমান্ডটি সংযোগ বিচ্ছিন্ন করতে হবে এবং আপনার ড্রপ করার চেষ্টা করছে না।

procpidকলামটির পুনঃনামকরণটি নোট করুন pid। দেখুন এই মেইলিং লিস্ট থ্রেড


11
এবং অবশ্যই, এটি একটি ডিবি সংযোগ থেকে তা করতে ভুলবেন না যা 'TARGET_DB' এর সাথে সংযোগ নয়, অন্যথায় আপনি 'ERROR' পান। একটি 'পোস্টগ্রিস' সংযোগটি ভালভাবে কাজ করে।
রব

3
আসলে এটি ক্লায়েন্টকে একে একে সংযোগ বিচ্ছিন্ন করে দেবে এবং যদি আপনি ক্লায়েন্ট তালিকার মাঝখানে থাকেন তবে এটিও সংযোগ বিচ্ছিন্ন হয়ে যাবে। ফলস্বরূপ, কিছু সংযোগ বেঁচে থাকবে। সুতরাং, সঠিক উত্তরটি ক্রেগ রিঞ্জার (নীচে দেখুন) see নির্বাচন করুন pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity যেখানে ডেটা নাম = বর্তমান_ড্যাটাবেস () এবং pg_stat_activity.pid <> পিজি_ব্যাকেন্ড_পিড ();
অ্যান্ড্রু সেলিভানোভ

1
তাদের বর্তমান লেনদেনটি শেষ হয়ে যাওয়ার পরে আমি কীভাবে সংযোগগুলি সংযোগ বিচ্ছিন্ন করতে পারি এবং প্রশ্নটিতে টেবিল (গুলি) ফেলে দিতে পারি?
পলকন

5
আমার ক্ষেত্রে ক্লায়েন্টরা দ্রুত পুনরায় সংযোগ স্থাপন করবে, তাই ; drop database TARGET_DB;জিনিসগুলি পুনরায় চেষ্টা শুরু করার সময় থেকে ডিবি চলে গেছে তা নিশ্চিত করার জন্য এটি আমার ক্ষেত্রে ভালভাবে কাজ করার ঠিক আগে রেখে দেওয়া ।
মাদুর শেফার

1
আমি এমনকি একটি জন্য টাকা দিতে হবে dropdb --force
টর্স্টেন ব্রোঞ্জার

125

পোস্টগ্র্রেএসকিউএল 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) FROM pg_stat_activity যেখানে ডেটা নাম = বর্তমান_ড্যাটাবেস () এবং pg_stat_activity.pid <> পিজি_ব্যাকেন্ড_পিড ();
অ্যান্ড্রু সেলিভানভ

26

আপনি pg_terminate_backend(int)ফাংশনটি ব্যবহার করে ডাটাবেস ফেলে দেওয়ার আগে সমস্ত সংযোগ নষ্ট করতে পারেন ।

আপনি সিস্টেম ভিউ ব্যবহার করে সমস্ত চলমান ব্যাকএন্ড পেতে পারেন pg_stat_activity

আমি পুরোপুরি নিশ্চিত নই, তবে নিম্নলিখিতগুলি সম্ভবত সমস্ত সেশনকে হত্যা করবে:

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

অবশ্যই আপনি সেই ডাটাবেসের সাথে নিজেকে যুক্ত নাও করতে পারেন


19

আপনার পোস্টগ্র্যাস্কেলের সংস্করণটির উপর নির্ভর করে আপনি সম্ভবত কোনও বাগে চলে যেতে পারেন, এটি তৈরি করে 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
আমি যা খুঁজছিলাম সেগুলি তবে (9.2 এবং তার বাইরেও ধরে নেওয়া) আপনাকে pg_stat_activity এর রেফারেন্সটি সরিয়ে ফেলা এবং প্রিপিডকে পিডে পরিবর্তন করতে হবে।
এমডিআর

2
পরিবর্তন করার পরে procpidকরতে pid9.3 এই স্নিপেট কাজ করে।
জেবি।

এমনকি pg_stat_activity অপসারণ ছাড়া? 9.2
MDR

ঠিক আছে. এখন আমি বুঝতে পারি, এটি টাইপো ছিল। ধন্যবাদ!
জেবি।

2
9.3 থেকে উপরে নির্বাচন করুন pg_terminate_backend (pid) FROM pg_stat_get_activity (NULL :: পূর্ণসংখ্যার) WHATE datid = (pg_datedia থেকে যেখানে SED নির্বাচন করুন যেখানে ডাটাবেস = 'আপনার_ড্যাটাবেস');
শন ভাদার

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

আশা করি এটি সহায়ক। স্কুলের জন্য @ জাস্টবোজকে ধন্যবাদ।


15

সংযুক্ত ক্লায়েন্টদের সংযোগ বিচ্ছিন্ন করতে আমি কেবল উবুন্টুতে পরিষেবাটি পুনরায় চালু করব।

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;

10

লিনাক্স কমান্ড প্রম্পটে, আমি প্রথমে এই কমান্ডটি sudo /etc/init.d/postgresql পুনঃসূচনাটি বেঁধে চলমান সমস্ত পোস্টগ্রেকসিএল প্রক্রিয়াগুলি বন্ধ করব

অন্যান্য postgresql প্রক্রিয়াগুলি এখনও চলছে কিনা তা পরীক্ষা করতে bg কমান্ডটি টাইপ করুন

তারপরে ড্রপডিব 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বিকল্প উপস্থাপন করবে ।

ড্রপ ডেটাবেস

ড্রপ ডেটাবেস একটি ডাটাবেস ড্রপ করে ... এছাড়াও, যদি অন্য কেউ লক্ষ্য ডাটাবেসের সাথে সংযুক্ত থাকে তবে আপনি নীচে বর্ণিত ফোর্স বিকল্পটি ব্যবহার না করে এই কমান্ডটি ব্যর্থ হবে ।

FORCE

লক্ষ্য ডাটাবেসের সমস্ত বিদ্যমান সংযোগ সমাপ্ত করার চেষ্টা করুন। লক্ষ্যযুক্ত ডাটাবেসে প্রস্তুত লেনদেন, সক্রিয় যৌক্তিক প্রতিরূপ স্লট বা সাবস্ক্রিপশন উপস্থিত থাকলে এটি শেষ হবে না।

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 ব্যতীত সমস্ত সংযোগ বিচ্ছিন্ন করে দিয়েছি এবং তারপরে ডাটাবেস এবং বৈশিষ্ট্যগুলিতে ডান চেটে নাম পরিবর্তন করতে সক্ষম হয়ে নতুন নাম টাইপ করতে পেরেছি।

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