首页 » PostgreSQL/GaussDB » How to Shell Script to execute SQL scripts( kill session) using psql/gsql for openGauss or PostgreSQL?

How to Shell Script to execute SQL scripts( kill session) using psql/gsql for openGauss or PostgreSQL?

Postgresql系为了避免像oracle ora-1555的问题,使用非undo的机制, 但需要周期性的做VACUUM,否则表上的dead tuples就没有办法复用或回收。 并且在PG或OG数据库Vacuum的最老位置是系统级的,如果有一个长事务存在,那长事务时间的其它表也没办法Vacuum,因为它不确认你是否会查其它表, 随时间推移,对于update,delete较多的表就会导致表膨胀较为明显,影响系统性能, 如果无法限制应用,此时可以定期的KILL一些长事务会话,如个人客户端,我们可以加一个shell到crontab中定期自动清理。

#!/bin/sh
# file   : kill_longtx.sh 
# author : weizhao zhang(anbob.com)
# purpose: Shell script to execute gsql command KILL Sessions in openGauss long than 30s


LOGPATH=/home/og/log

if [ ! -d "$LOGPATH" ];then
  mkdir $LOGPATH
  if [ $? -ne 0 ]
  then
      echo "$LOGPATH not exists and create failed!"
      exit 90
  fi
fi

LOGFILE=$LOGPATH/kill_longtx.log
SQLLOG=$LOGPATH/killed_sessions.log
SQLSCRIPT=$LOGPATH/kill_longtx.sql
# SQLLOG=$LOGPATH/killed`date +"%Y_%m_%d_%H_%M"`.log

if [ ! -f "$SQLSCRIPT" ];then
  mkdir $LOGPATH
  if [ $? -ne 0 ]
  then
      echo "$SQLSCRIPT not exists!"
      exit 90
  fi
fi

#Set the value of variable
DATABASE="anbob"
PORT=6432

echo " " >> $LOGFILE 2>&1
echo "START ----`date`" >> $LOGFILE 2>&1

#Assign table count to variable
SESSION_COUNT=$(gsql -d $DATABASE  -p $PORT  -t -c "select count(1) from pg_stat_activity where state='idle in transaction' and extract(epoch FROM now() - query_start)>30")

if [ $SESSION_COUNT -gt 0 ]
then

#Print the value of variable
echo "Found long transaction sessions:$SESSION_COUNT " >> $LOGFILE 2>&1

#Execute few psql commands:
gsql  -d $DATABASE  -p $PORT -a -q -f $SQLSCRIPT -L $SQLLOG

gsql_exit_status = $?

if [ $gsql_exit_status != 0 ]; then
    echo "gsql failed while trying to run this sql script" >> $LOGFILE 2>&1
    exit $psql_exit_status
fi


else
echo "Not found long transaction sessions:$SESSION_COUNT " >> $LOGFILE 2>&1

fi

echo "END ----`date`" >> $LOGFILE 2>&1

Note:
注意我这里使用了是openGauss, 所以是gsql命令行工具,如果是postgresql可以替换为psql通用, 逻辑是调用kill_longtx.sh 检查一些有事务的会话,这里过滤的是近期无活动的30s以上的会话,如果你是oracle dba,可以理解为last_call_et > 30s。 当然你可以增加自己的过滤条件,如application like. 如果个数>0 执行kill_longtx.sql脚本,中调用pg_terminate_backend() 终止了会话, 期间会记录日志(每次的调用和KILL的会话)。

gsql的使用的几个参数选项。
# -h PostgreSQL server IP address
# -d database name
# -U user name
# -p port which PostgreSQL server is listening on
# -f path to SQL script
# -a all echo
# -q quiet
# -o spool output to file
# -L send session log to file

kill_longtx.sql

-- kill long tx by xx client

-- log datetime
select now();

-- log session and kill session
select datid,datname,pid,sessionid,usename,application_name,backend_start,xact_start,query_start,waiting,state,extract(epoch FROM now() - query_start) waited ,pg_terminate_backend(pid) from pg_stat_activity where state='idle in transaction' and extract(epoch FROM now() - query_start)>30;

ok ,然后就可以在crontab中增加调度,调用像kill_longtx.sh定期做一些事情。

打赏

对不起,这篇文章暂时关闭评论。