it-swarm.asia

إسقاط القوة ديسيبل بينما قد يتم توصيل الآخرين

أحتاج إلى إزالة قاعدة بيانات من كتلة PostgreSQL DB. كيف يمكنني القيام بذلك حتى لو كانت هناك اتصالات نشطة؟ أحتاج إلى نوع من -force العلم الذي سيسقط جميع الاتصالات ثم قاعدة البيانات.

كيف يمكنني تنفيذه؟

أنا أستخدم dropdb حاليًا ، ولكن هناك أدوات أخرى ممكنة.

126
Alex

في PostgreSQL*، لا يمكنك إسقاط قاعدة بيانات أثناء اتصال العملاء بها.

على الأقل ، ليس مع الأداة المساعدة dropdb - وهي مجرد غلاف بسيط حول DROP DATABASE استعلام الخادم.

فيما يلي حل قوي للغاية:

اتصل بخادمك باسم مستخدم خارق ، باستخدام psql أو عميل آخر. لا لا تستخدم قاعدة البيانات التي تريد إسقاطها.

psql -h localhost postgres postgres

الآن باستخدام عميل قاعدة بيانات عادي يمكنك فرض إسقاط قاعدة البيانات باستخدام ثلاث خطوات بسيطة:

  1. تأكد من أنه لا يمكن لأي شخص الاتصال بقاعدة البيانات هذه. يمكنك استخدام إحدى الطرق التالية (تبدو الثانية أكثر أمانًا ، ولكنها لا تمنع الاتصالات من المستخدمين الخارقين).

    /* Method 1: update system catalog */
    UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'mydb';
    
    /* Method 2: use ALTER DATABASE. Superusers still can connect!
    ALTER DATABASE mydb CONNECTION LIMIT 0; */
    
  2. فرض قطع اتصال كافة العملاء المتصلين بقاعدة البيانات هذه باستخدام pg_terminate_backend .

    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'mydb';
    
    /* For old versions of PostgreSQL (up to 9.1), change pid to procpid:
    
    SELECT pg_terminate_backend(procpid)
    FROM pg_stat_activity
    WHERE datname = 'mydb'; */
    
  3. إسقاط قاعدة البيانات.

    DROP DATABASE mydb;
    

تتطلب الخطوة 1 امتيازات مستخدم خارق للطريقة الأولى ، وامتيازات مالك قاعدة البيانات للشخص الثاني. تتطلب الخطوة 2 امتيازات مستخدم مميز . تتطلب الخطوة 3 امتياز مالك قاعدة البيانات .


ينطبق هذا على جميع إصدارات PostgreSQL ، حتى الإصدار 12. النسخة 13 لها DROP DATABASE mydb FORCE


178
filiprem

باستخدام إجابة @ filiprem في حالتي وتبسيطها:

-- Connecting to the current user localhost's postgres instance
psql

-- Making sure the database exists
SELECT * from pg_database where datname = 'my_database_name'

-- Disallow new connections
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'my_database_name';
ALTER DATABASE my_database_name CONNECTION LIMIT 1;

-- Terminate existing connections
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'my_database_name';

-- Drop database
DROP DATABASE my_database_name
9
Dorian

هناك is طريقة للقيام بذلك باستخدام أدوات شل dropdb & pg_ctl (أو pg_ctlcluster في دبيان ومشتقاته). لكن @ طريقة filiprem متفوقة لعدة أسباب:

  • يفصل فقط المستخدمين من قاعدة البيانات المعنية.
  • لا تحتاج إلى إعادة تشغيل نظام المجموعة بالكامل.
  • يمنع إعادة الاتصال الفوري ، ربما يفسد الأمر dropdb.

انا اقتبس man pg_ctlcluster:

مع ال --force الخيار يستخدم الوضع "السريع" الذي يعيد جميع المعاملات النشطة ، ويفصل العملاء على الفور ، وبالتالي يغلق بشكل نظيف. إذا لم يفلح ذلك ، تتم محاولة إيقاف التشغيل مرة أخرى في الوضع "الفوري" ، والذي يمكن أن يترك المجموعة في حالة غير متناسقة وبالتالي سيؤدي إلى تشغيل الاسترداد في البداية التالية. إذا كان هذا لا يزال لا يساعد ، يتم قتل عملية postmaster. يخرج مع 0 عند النجاح ، مع 2 إذا لم يكن الخادم قيد التشغيل ، ومع 1 في حالات فشل أخرى. يجب استخدام هذا الوضع فقط عندما يكون الجهاز على وشك إيقاف التشغيل.

pg_ctlcluster 9.1 main restart --force

أو

pg_ctl restart -D datadir -m fast

أو

pg_ctl restart -D datadir -m immediate

متبوعًا فورًا بـ:

dropdb mydb

ربما في سيناريو لخلافة فورية.

7
Erwin Brandstetter

إذا كنت تستخدم شيئًا مثل RDS حيث تضعك الاتصالات بدون قاعدة بيانات محددة في قاعدة البيانات التي طلبت أن يتم إنشاؤها بشكل افتراضي ، يمكنك القيام بهذا البديل لتتجنب كونك آخر اتصال مفتوح.

 DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist; 

 CREATE DATABASE temporary_db_that_shouldnt_exist with OWNER your_user; 

 \connect temporary_db_that_shouldnt_exist 
 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'the_db_you_want_removed'; 


 DROP DATABASE IF EXISTS the_db_you_want_removed; 
 -- 
 -- Name: the_db_you_want_removed; Type: DATABASE; Schema: -; Owner: your_user 
 -- 

 CREATE DATABASE savings_champion WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; 


 ALTER DATABASE the_db_you_want_removed OWNER TO your_user; 

 \connect the_db_you_want_removed 

 DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;
0
Jharwood