kill_db_locks.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/env python3
  2. """
  3. 查找并杀掉数据库端的僵尸连接,释放 knowledge 表的锁
  4. """
  5. import os, psycopg2
  6. from dotenv import load_dotenv
  7. _dir = os.path.dirname(os.path.abspath(__file__))
  8. _root = os.path.normpath(os.path.join(_dir, '..', '..'))
  9. load_dotenv(os.path.join(_root, '.env'))
  10. conn = psycopg2.connect(
  11. host=os.getenv('KNOWHUB_DB'),
  12. port=int(os.getenv('KNOWHUB_PORT', 5432)),
  13. user=os.getenv('KNOWHUB_USER'),
  14. password=os.getenv('KNOWHUB_PASSWORD'),
  15. database=os.getenv('KNOWHUB_DB_NAME'),
  16. connect_timeout=10
  17. )
  18. conn.autocommit = True
  19. cur = conn.cursor()
  20. print("Connected.\n")
  21. # 1. 查所有非 idle 的活跃连接
  22. print("=== Active connections (non-idle) ===")
  23. cur.execute("""
  24. SELECT pid, state, now() - query_start as duration, query
  25. FROM pg_stat_activity
  26. WHERE state != 'idle' AND pid != pg_backend_pid()
  27. ORDER BY query_start
  28. """)
  29. rows = cur.fetchall()
  30. print(f"Found {len(rows)} active connections.\n")
  31. for r in rows:
  32. print(f" PID={r[0]} state={r[1]} duration={r[2]}")
  33. print(f" query: {str(r[3])[:150]}")
  34. print()
  35. # 2. 查所有 idle in transaction 的连接(这些最可能持有锁)
  36. print("=== Idle-in-transaction connections ===")
  37. cur.execute("""
  38. SELECT pid, state, now() - query_start as duration, query
  39. FROM pg_stat_activity
  40. WHERE state = 'idle in transaction' AND pid != pg_backend_pid()
  41. ORDER BY query_start
  42. """)
  43. idle_tx = cur.fetchall()
  44. print(f"Found {len(idle_tx)} idle-in-transaction connections.\n")
  45. for r in idle_tx:
  46. print(f" PID={r[0]} duration={r[2]}")
  47. print(f" last query: {str(r[3])[:150]}")
  48. print()
  49. # 3. 杀掉所有非当前的 非idle 和 idle-in-transaction 连接
  50. cur.execute("""
  51. SELECT pid FROM pg_stat_activity
  52. WHERE pid != pg_backend_pid()
  53. AND (state != 'idle' OR state = 'idle in transaction')
  54. """)
  55. pids = [r[0] for r in cur.fetchall()]
  56. print(f"=== Terminating {len(pids)} backend connections ===")
  57. for pid in pids:
  58. try:
  59. cur.execute("SELECT pg_terminate_backend(%s)", (pid,))
  60. print(f" Killed PID {pid}")
  61. except Exception as e:
  62. print(f" Failed PID {pid}: {e}")
  63. print("\nDone. Try opening knowledge table in Navicat now.")
  64. cur.close()
  65. conn.close()