איך עוקפים את ההגנה מפני חזרה למספרים קודמים (wraparound) של מזהה העסקה (TXID)

בדף הזה מוסבר מה אפשר לעשות כשמסד הנתונים נתקל בהגנה מפני גלישה של מזהה טרנזקציה ב-PostgreSQL. היא מופיעה כהודעת ERROR, באופן הבא:

database is not accepting commands to avoid wraparound data loss in database
DB_NAME.

Stop the postmaster and vacuum that database in single-user mode.

You might also need to commit or roll back old prepared transactions, or drop
stale replication slots.

לחלופין, יכול להיות שתופיע הודעת WARNING כמו זו:

database DB_NAME must be vacuumed within 10985967 transactions.

To avoid a database shutdown, execute a database-wide VACUUM in that database.

דיווח על cloudsql.enable_maintenance_mode

כברירת מחדל, אי אפשר להריץ DDL או DML ברגע שמסד הנתונים נמצא במצב wraparound, אבל Cloud SQL ל-PostgreSQL מציע מצב תחזוקה למקרי חירום שנותן עוד 500,000 מזהי עסקאות כדי לצאת מהמצב הזה בלי להפעיל מחדש את השרת במצב של משתמש יחיד.

כדי להפעיל את מצב התחזוקה, מגדירים את cloudsql.enable_maintenance_mode ל-on בסשן של מסד הנתונים לפני שמשתמשים בפקודות שדורשות מזהה עסקה:

SET cloudsql.enable_maintenance_mode = 'on';
[ your SQL, DML or DDL commands here ]

צריך לעשות את זה בסשן שבו מבצעים את התחזוקה, לפני שמבצעים פעולה כלשהי שדורשת מזהה עסקה.

סקירה כללית של השלבים

  • מזהים את מסד הנתונים ואת הטבלאות שגורמים ל-wraparound.

  • בודקים אם יש משהו שמעכב את (AUTO)VACUUM (לדוגמה, מזהה עסקה תקוע).

  • מדידת המהירות של AUTOVACUUM. אם הוא איטי, אפשר לנסות להאיץ אותו.

  • אם צריך, מריצים עוד כמה פקודות VACUUM באופן ידני.

  • לבדוק דרכים אחרות לזרז את פעולת ה-VACUUM. לפעמים הדרך המהירה ביותר היא למחוק את הטבלה או כמה אינדקסים.

רבות מההמלצות לערכים של דגלים לא מדויקות בכוונה, כי הן תלויות בפרמטרים רבים של מסד הנתונים. כדי לקבל ניתוח מעמיק יותר של הנושא, קראו את המסמכים שמקושרים בסוף הדף הזה.

מאתרים את מסד הנתונים ואת הטבלה שגורמים ל-wraparound

איתור מסד הנתונים

כדי לגלות איזה מסד נתונים מכיל את הטבלאות שגורמות ל-wraparound, מריצים את השאילתה הבאה:

SELECT datname, 
       age(datfrozenxid), 
       2^31-1000000-age(datfrozenxid) as remaining
  FROM pg_database
 ORDER BY 3

מסד הנתונים עם ערך remaining שקרוב ל-0 הוא זה שגורם לבעיה.

חיפוש הטבלה

מתחברים למסד הנתונים הזה ומריצים את השאילתה הבאה:

SELECT c.relnamespace::regnamespace as schema_name,
       c.relname as table_name,
       greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age,
       2^31-1000000-greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as remaining
  FROM pg_class c
  LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
 WHERE c.relkind IN ('r', 'm')
 ORDER BY 4;

השאילתה הזו מחזירה את הטבלה או הטבלאות שגורמות לבעיה.

לטבלאות TEMPORARY

אם הערך של schema_name מתחיל ב-pg_temp_, הדרך היחידה לפתור את הבעיה היא למחוק את הטבלה, כי PostgreSQL לא מאפשר לבצע VACUUM בטבלאות זמניות שנוצרו בסשנים אחרים. לפעמים, אם הסשן הזה פתוח ונגיש, אפשר לבצע את הפעולה vacuum בטבלה, אבל בדרך כלל זה לא המצב. כדי למחוק את הטבלה הזמנית, משתמשים בהצהרות ה-SQL הבאות:

SET cloudsql.enable_maintenance_mode = 'on'; /* get extra transaction ids */
DROP TABLE pg_temp_N.TABLE_NAME;

מחליפים את מה שכתוב בשדות הבאים:

  • ‫N: מספר הסכימה הזמנית.

  • ‫TABLE_NAME: שם הטבלה הזמנית שרוצים למחוק.

אם זה היה החוסם היחיד, אז תוך דקה בערך, ה-autovacuum יזהה את השינוי הזה ויקדם את ה-datfrozenxid ב-pg_database. הפעולה הזו פותרת את מצב הקריאה בלבד של הגנת הגלישה.

טבלאות רגילות

בטבלאות רגילות (כלומר לא זמניות), ממשיכים לשלבים הבאים כדי לבדוק אם משהו חוסם את הניקוי, אם ה-VACUUM פועל מספיק מהר ואם הטבלה הכי חשובה עוברת ניקוי.

בדיקה אם מזהה העסקה תקוע

אחת מהסיבות האפשריות לכך שהמערכת תגיע למצב של מחסור במזהי טרנזקציות היא ש-PostgreSQL לא יכולה להקפיא (כלומר, לסמן כגלויה לכל הטרנזקציות) מזהי טרנזקציות שנוצרו אחרי שהטרנזקציה הישנה ביותר שפועלת כרגע התחילה. הסיבה לכך היא כללי בקרת בו-זמניות בכמה גרסאות (MVCC). במקרים קיצוניים, העסקאות האלה יכולות להיות כל כך ישנות, עד ש-VACUUM לא יכול לנקות עסקאות ישנות בכל מגבלת ה-wraparound של 2 מיליארד מזהי עסקאות, והמערכת כולה מפסיקה לקבל DML חדש. בדרך כלל מופיעות גם אזהרות בקובץ היומן, כמו WARNING: oldest xmin is far in the past.

אפשר לעבור לאופטימיזציה רק אחרי שהבעיה במזהה העסקה התקוע נפתרה.

הנה ארבע סיבות אפשריות לכך שמזהה עסקה נתקע, ומידע על הדרכים לפתור כל אחת מהן:

  • טרנזקציות שפועלות זמן רב: מזהים אותן ומבטלים או מסיימים את ה-backend כדי לבטל את החסימה של ה-vacuum.
  • עסקאות הכנה מיותמות: החזירו את העסקאות האלה למצב הקודם.
  • משבצות רפליקציה נטושות: צריך להסיר את המשבצות הנטושות.
  • טרנזקציה שפועלת זמן רב ברפליקה, עם hot_standby_feedback = on: מזהים אותן ומבטלים או מסיימים את הקצה העורפי כדי לבטל את החסימה של ה-vacuum.

בתרחישים האלה, השאילתה הבאה מחזירה את הגיל של העסקה הישנה ביותר ואת מספר העסקאות שנותרו עד ל-wraparound:

 WITH q AS (
SELECT
  (SELECT max(age(backend_xmin))
      FROM pg_stat_activity  WHERE state != 'idle' )       AS oldest_running_xact_age,
  (SELECT max(age(transaction)) FROM pg_prepared_xacts)    AS oldest_prepared_xact_age,
  (SELECT max(greatest(age(catalog_xmin),age(xmin))) FROM pg_replication_slots)        AS oldest_replication_slot_age,
  (SELECT max(age(backend_xmin)) FROM pg_stat_replication) AS oldest_replica_xact_age
)
SELECT *,
       2^31 - oldest_running_xact_age AS oldest_running_xact_left,
       2^31 - oldest_prepared_xact_age AS oldest_prepared_xact_left,
       2^31 - oldest_replication_slot_age AS oldest_replication_slot_left,
       2^31 - oldest_replica_xact_age AS oldest_replica_xact_left
FROM q;

השאילתה הזו עשויה להחזיר כל אחד מהערכים של ‎*_left שדווחו קרוב למיליון או פחות ממיליון לפני הגלישה. הערך הזה הוא מגבלת ההגנה מפני גלישה, שבה PostgreSQL מפסיק לקבל פקודות כתיבה חדשות. במקרה כזה, עיינו בקטע הסרת חסימות של VACUUM או כוונון VACUUM.

לדוגמה, השאילתה הקודמת עשויה להחזיר:

┌─[ RECORD 1 ]─────────────────┬────────────┐
│ oldest_running_xact_age      │ 2146483655 │
│ oldest_prepared_xact_age     │ 2146483655 │
│ oldest_replication_slot_age  │ ¤          │
│ oldest_replica_xact_age      │ ¤          │
│ oldest_running_xact_left     │ 999993     │
│ oldest_prepared_xact_left    │ 999993     │
│ oldest_replication_slot_left │ ¤          │
│ oldest_replica_xact_left     │ ¤          │
└──────────────────────────────┴────────────┘

כאשר oldest_running_xact_left ו-oldest_prepared_xact_left נמצאים בטווח של מיליון אחד של הגנת גלישה. במקרה כזה, קודם צריך להסיר את החסימות כדי ש-VACUUM יוכל להמשיך.

הסרת חסימות של VACUUM

עסקאות ממושכות

בשאילתה הקודמת, אם הערך של oldest_running_xact שווה לערך של oldest_prepared_xact, עוברים לקטע עסקאות הכנה מיותמות, כי הערך של latest running כולל גם את עסקאות ההכנה.

יכול להיות שתצטרכו קודם להריץ את הפקודה הבאה בתור המשתמש postgres:

GRANT pg_signal_backend TO postgres;

אם הטרנזקציה הבעייתית שייכת לאחד ממשתמשי המערכת (שמתחילים ב-cloudsql...), אי אפשר לבטל אותה ישירות. כדי לבטל את הפעולה, צריך להפעיל מחדש את מסד הנתונים.

כדי לזהות שאילתה שפועלת זמן רב, ולבטל או לסיים אותה כדי לבטל את החסימה של ה-vacuum, קודם בוחרים כמה מהשאילתות הישנות ביותר. השורה LIMIT 10 עוזרת להתאים את התוצאה למסך. יכול להיות שתצטרכו לחזור על הפעולה הזו אחרי שתפתרו את השאילתות הישנות ביותר שפועלות.

SELECT pid,
       age(backend_xid) AS age_in_xids,
       now() - xact_start AS xact_age,
       now() - query_start AS query_age,
       state,
       query
 FROM pg_stat_activity
 WHERE state != 'idle'
 ORDER BY 2 DESC
 LIMIT 10;

אם הערך של age_in_xids הוא NULL, המשמעות היא שלא הוקצה לעסקה מזהה עסקה קבוע ואפשר להתעלם ממנה.

לבטל את השאילתות שבהן הערך של xids_left_to_wraparound מתקרב למיליון.

אם הערך של state הוא active, אפשר לבטל את השאילתה באמצעות SELECT pg_cancel_backend(pid);. אחרת, צריך לסיים את כל החיבור באמצעות SELECT pg_terminate_backend(pid);, כאשר pid הוא ה-pid מהשאילתה הקודמת.

עסקאות הכנה מיותמות

הצגת רשימה של כל העסקאות המוכנות:

DB_NAME=> SELECT age(transaction),* FROM pg_prepared_xacts ;
┌─[ RECORD 1 ]┬───────────────────────────────┐
│ age         │ 2146483656                    │
│ transaction │ 2455493932                    │
│ gid         │ trx_id_pin                    │
│ prepared    │ 2021-03-03 16:54:07.923158+00 │
│ owner       │ postgres                      │
│ database    │ DB_NAME                       │
└─────────────┴───────────────────────────────┘

מבטלים את העסקאות המוכנות היתומות הישנות ביותר באמצעות הערך של gid מהשאילתה האחרונה (במקרה הזה, trx_id_pin) בתור מזהה העסקה:

ROLLBACK PREPARED trx_id_pin;

לחלופין, אפשר להעביר את השינויים:

COMMIT PREPARED trx_id_pin;

הסבר מלא מופיע במסמכי התיעוד של SQL ROLLBACK PREPARED.

משבצות רפליקציה נטושות

אם משבצת הרפליקציה ננטשה כי הרפליקה הקיימת הופסקה, הושהתה או שיש בה בעיה אחרת, אפשר למחוק את הרפליקה ממסוף gcloud או Cloud de Confiance .

קודם כל, צריך לוודא שהרפליקה לא מושבתת, כמו שמתואר במאמר ניהול רפליקות לקריאה בלבד. אם הרפליקה מושבתת, מפעילים אותה מחדש. אם זמן האחזור עדיין גבוה, מוחקים את הרפליקה,

משבצות הרפליקציה מופיעות בתצוגת המערכת pg_replication_slots.

השאילתה הבאה מאחזרת את המידע הרלוונטי:

SELECT *, age(xmin) AS age FROM pg_replication_slots;
┌─[ RECORD 1 ]────────┬─────────────────────────────────────────────────┐
│ slot_name           │ cloudsql_1_355b114b_9ff4_4bc3_ac88_6a80199bd738 │
│ plugin              │ ¤                                               │
│ slot_type           │ physical                                        │
│ datoid              │ ¤                                               │
│ database            │ ¤                                               │
│ active              │ t                                               │
│ active_pid          │ 1126                                            │
│ xmin                │ 2453745071                                      │
│ catalog_xmin        │ ¤                                               │
│ restart_lsn         │ C0/BEF7C2D0                                     │
│ confirmed_flush_lsn │ ¤                                               │
│ age                 │ 59                                              │
└─────────────────────┴─────────────────────────────────────────────────┘

בדוגמה הזו, הערך של pg_replication_slots תקין (age == 59). אם הגיל היה קרוב ל-2 מיליארד, הייתם רוצים למחוק את המשבצת. אין דרך קלה לדעת איזו רפליקה היא איזו במקרה שהשאילתה מחזירה כמה רשומות. לכן, צריך לבדוק את כולן למקרה שיש טרנזקציה ממושכת באחת מהרפליקות.

טרנזקציות ממושכות ברפליקות

בודקים את הרפליקות כדי למצוא את הטרנזקציה הפעילה הכי ישנה שבה hot_standby_feedback מוגדר כ-on, ומשביתים אותה ברפליקה.

העמודה backend_xmin בתצוגה pg_stat_replication מכילה את הערך הישן ביותר של TXID שנדרש ברפליקה.

כדי להזיז אותו קדימה, צריך לעצור את השאילתה שמעכבת אותו ברפליקה. כדי לגלות איזו שאילתה מעכבת את התהליך, משתמשים בשאילתה ב-Long running transactions, אבל הפעם מריצים אותה על הרפליקה.

אפשרות נוספת היא להפעיל מחדש את הרפליקה.

הגדרת VACUUM

מגדירים את שני הדגלים הבאים:

  • autovacuum_vacuum_cost_delay = 0

  • autovacuum_work_mem = 1048576

הראשונה משביתה את כל ההגבלות על הדיסק לביצוע פעולת VACUUM על ידי PostgreSQL, כדי ש-VACUUM תוכל לפעול במהירות מלאה. כברירת מחדל, הפעולה של autovacuum מוגבלת כדי לא לנצל את כל הקלט/פלט של הדיסק בשרתים האיטיים ביותר.

הדגל השני, autovacuum_work_mem, מקטין את מספר סבבי הניקוי של האינדקס. אם אפשר, הוא צריך להיות גדול מספיק כדי לאחסן את כל המזהים של השורות המתות בטבלה ש-VACUUM הולך לנקות. כשמגדירים את הערך הזה, חשוב לזכור שזהו נפח הזיכרון המקומי המקסימלי שכל VACUUM שפועל יכול להקצות. חשוב לוודא שאתם לא מאפשרים יותר ממה שזמין, ושיש לכם רזרבה. אם משאירים את מסד הנתונים במצב קריאה בלבד, צריך להביא בחשבון גם את הזיכרון המקומי שמשמש לשאילתות לקריאה בלבד.

ברוב המערכות, צריך להשתמש בערך המקסימלי (1GB או 1048576kB, כמו שמוצג בדוגמה). הערך הזה מתאים לעד כ-178 מיליון רשומות לא פעילות. אם יש יותר, זה עדיין גורם למספר מעברים של סריקת אינדקס.

הדגלים האלה ודגלים אחרים מוסברים בפירוט במאמר אופטימיזציה, מעקב ופתרון בעיות של פעולות VACUUM ב-PostgreSQL.

אחרי שמגדירים את הדגלים האלה, מפעילים מחדש את מסד הנתונים כדי שה-autovacuum יתחיל עם הערכים החדשים.

אתם יכולים להשתמש בתצוגה pg_stat_progress_vacuum כדי לעקוב אחרי ההתקדמות של פקודות VACUUM שהופעלו על ידי autovacuum. בתצוגה הזו מוצגות פקודות VACUUM שפועלות בכל מסדי הנתונים, וגם בטבלאות (יחסים) ממסדי נתונים אחרים שאי אפשר לחפש בהם את שם הטבלה באמצעות העמודה relid בתצוגה.

כדי לזהות את מסדי הנתונים והטבלאות שצריך לבצע בהם פעולת VACUUM, משתמשים בשאילתות מתוך אופטימיזציה, מעקב ופתרון בעיות של פעולות VACUUM ב-PostgreSQL. אם ה-VM של השרת חזק מספיק ויש לו רוחב פס ליותר תהליכי VACUUM מקבילים מאלה שהופעלו על ידי autovacuum, אפשר להפעיל כמה תהליכי vacuum ידניים.

בדיקת המהירות של VACUUM

בקטע הזה מוסבר איך לבדוק את מהירות הפעולה של VACUUM ואיך להאיץ אותה, אם צריך.

בדיקת autovacuum שפועלים

כל הקצוות העורפיים שמריצים את VACUUM גלויים בתצוגת המערכת pg_stat_progress_vacuum.

אם השלב הנוכחי הוא scanning heap, אפשר לעקוב אחרי ההתקדמות באמצעות השינויים בעמודה heap_blks_scanned. לצערנו, אין דרך קלה לקבוע את מהירות הסריקה בשלבים אחרים.

הערכת מהירות הסריקה של VACUUM

כדי להעריך את מהירות הסריקה, קודם צריך לאחסן את ערכי הבסיס ואז לחשב את השינוי לאורך זמן כדי להעריך את זמן ההשלמה. קודם צריך לשמור תמונת מצב של heap_blks_scanned יחד עם חותמת זמן באמצעות שאילתת תמונת המצב הבאה:

SELECT set_config('save.ts', clock_timestamp()::text, false),
       set_config('save.heap_blks_scanned', heap_blks_scanned::text, false)
FROM pg_stat_progress_vacuum
WHERE datname = 'DB_NAME';

אנחנו לא יכולים לשמור שום דבר בטבלאות שכבר נמצאות במצב wraparound, לכן צריך להשתמש ב-set_config(flag, value) כדי להגדיר שני דגלים שמוגדרים על ידי המשתמש – save.ts ו-save.heap_blks_scanned – לערכים הנוכחיים מ-pg_stat_progress_vacuum.

בשאילתה הבאה, נשתמש בשני הערכים האלה כבסיס להשוואה כדי לקבוע את המהירות ולהעריך את זמן ההשלמה.

אחרי ששומרים את ערכי הבסיס, אפשר להריץ את השאילתה הבאה:

with q as (
    SELECT datname,
           phase,
           heap_blks_total,
           heap_blks_scanned,
           clock_timestamp() - current_setting('save.ts')::timestamp AS ts_delta,
           heap_blks_scanned - current_setting('save.heap_blks_scanned')::bigint AS scanned_delta
     FROM pg_stat_progress_vacuum
     WHERE datname = 'DB_NAME'
), q2 AS (
SELECT *,
       scanned_delta / extract('epoch' FROM ts_delta) AS pages_per_second
  FROM q
)
SELECT *,
       (heap_blks_total - heap_blks_scanned) / pages_per_second AS remaining_time
  FROM q2
;
┌─[ RECORD 1 ]──────┬──────────────────┐
│ datname           │ DB_NAME          │
│ phase             │ scanning heap    │
│ heap_blks_total   │ 9497174          │
│ heap_blks_scanned │ 18016            │
│ ts_delta          │ 00:00:40.30126   │
│ as_scanned_delta  │ 11642            │
│ pages_per_second  │ 288.87434288655  │
│ remaining_time    │ 32814.1222418038 │
└───────────────────┴──────────────────┘

השאילתה הזו משווה בין הערכים הנוכחיים לבין ערכי הבסיס השמורים ומחשבת את pages_per_second ו-remaining_time, מה שמאפשר לנו להחליט אם VACUUM פועל מהר מספיק או אם אנחנו רוצים להאיץ אותו. הערך remaining_time מיועד רק לשלב scanning heap. גם שלבים אחרים לוקחים זמן, לפעמים אפילו יותר. אתם יכולים לקרוא מידע נוסף על פעולת ה-VACUUM ולעיין בפוסטים בבלוגים באינטרנט שעוסקים בחלק מההיבטים המורכבים של הפעולה.

האצת VACUUM

הדרך הקלה והמהירה ביותר לגרום לסריקה של VACUUM לפעול מהר יותר היא להגדיר את autovacuum_vacuum_cost_delay=0. אפשר לעשות זאת דרך מסוףCloud de Confiance .

לצערנו, פקודת ה-VACUUM שכבר פועלת לא תזהה את הערך הזה, ויכול להיות שתצטרכו להפעיל מחדש את מסד הנתונים.

אחרי ההפעלה מחדש, יכול להיות שתראו תוצאה דומה לזו:

┌─[ RECORD 1 ]──────┬──────────────────┐
│ datname           │ DB_NAME          │
│ phase             │ scanning heap    │
│ heap_blks_total   │ 9497174          │
│ heap_blks_scanned │ 222382           │
│ ts_delta          │ 00:00:21.422615  │
│ as_scanned_delta  │ 138235           │
│ pages_per_second  │ 6452.76031894332 │
│ remaining_time    │ 1437.33713040171 │
└───────────────────┴──────────────────┘

בדוגמה הזו, המהירות עלתה מפחות מ-300 דפים לשנייה לכ-6,500 דפים לשנייה, והזמן המשוער שנותר לשלב הסריקה של ה-heap ירד מ-9 שעות ל-23 דקות.

מהירות הסריקה של השלבים האחרים לא קלה למדידה, אבל הם אמורים להראות האצה דומה.

כדאי גם להגדיר את autovacuum_work_mem לגודל המקסימלי האפשרי כדי להימנע ממעברים מרובים על אינדקסים. סבב אינדקס מתרחש בכל פעם שהזיכרון מתמלא במצביעים ל-tuples מתים.

אם לא משתמשים במסד הנתונים בדרך אחרת, מגדירים את autovacuum_work_mem כך שיהיו כ-80% זיכרון פנוי אחרי שמאפשרים את הכמות הנדרשת ל-shared_buffers. זו המגבלה העליונה לכל אחד מתהליכי ה-VACUUM שהופעלו על ידי autovacuum. אם רוצים להמשיך להריץ עומסי עבודה לקריאה בלבד, צריך להשתמש בפחות זיכרון.

דרכים נוספות לשיפור המהירות

הימנעות מביצוע vacuuming לאינדקסים

בטבלאות ענקיות, הפעולה VACUUM משקיעה את רוב הזמן בניקוי אינדקסים.

ב-PostgreSQL 14 יש אופטימיזציות מיוחדות למניעת ניקוי אינדקסים אם המערכת נמצאת בסכנה של wraparound.

ב-PostgreSQL בגרסאות 12 ו-13, אפשר להריץ ידנית את ההצהרה הבאה:

VACUUM (INDEX_CLEANUP OFF, TRUNCATE OFF) TABLE_NAME;

מחליפים את TABLE_NAME בשם הטבלה שרוצים לבצע בה את פעולת ה-VACUUM.

בגרסאות 11 ומטה, אפשר DROP את האינדקס לפני הפעלת ה-vacuum וליצור אותו מחדש מאוחר יותר.

כדי להסיר את האינדקס כש-autovacuum כבר פועל בטבלה הזו, צריך לבטל את ה-vacuum שפועל ואז להריץ מיד את הפקודה להסרת האינדקס לפני ש-autovacuum יצליח להפעיל שוב את ה-vacuum בטבלה הזו.

קודם כל, מריצים את ההצהרה הבאה כדי למצוא את ה-PID של תהליך ה-autovacuum שרוצים לסיים:

SELECT pid, query 
  FROM pg_stat_activity
 WHERE state != 'idle'
   AND query ilike '%vacuum%';

לאחר מכן, מריצים את ההצהרות הבאות כדי לסיים את פעולת ה-VACUUM שפועלת ולמחוק אינדקס אחד או יותר:

SET cloudsql.enable_maintenance_mode = 'on'; /* get extra transaction ids */
SELECT pg_terminate_backend(PID);
DROP INDEX INDEX_1;
DROP INDEX INDEX_2;

מחליפים את מה שכתוב בשדות הבאים:

  • ‫PID: מזהה התהליך של תהליך ה-autovacuum שרוצים לסיים.

  • ‫INDEX_1 ו-INDEX_2: שמות האינדקסים שרוצים למחוק.

הסרת הטבלה הבעייתית

במקרים נדירים, אפשר למחוק את הטבלה. לדוגמה, אם מדובר בטבלה שקל לשחזר ממקור אחר כמו גיבוי או מסד נתונים אחר.

עדיין צריך להשתמש ב-cloudsql.enable_maintenance_mode = 'on' וכנראה גם לסיים את ה-VACUUM בטבלה הזו, כמו שמוצג בקטע הקודם.

VACUUM FULL

במקרים נדירים, מהיר יותר להריץ את VACUUM FULL FREEZE, בדרך כלל כשהטבלה מכילה רק חלק קטן של טאפלים פעילים. אפשר לבדוק את זה בתצוגה pg_stat_user_tables (אלא אם הייתה קריסה שמחקה את הנתונים הסטטיסטיים).

הפקודה VACUUM FULL מעתיקה את ה-tuples הפעילים לקובץ חדש, כך שצריך להיות מספיק מקום פנוי לקובץ החדש ולאינדקסים שלו.

המאמרים הבאים