背景
生产线上的gp数据库前几天突然拒绝服务了,具体现象会在jar包中报如下图错误。
The distributed transaction 'Prepare' broadcast failed to one or more segments for gid = 1634870850-0000771545. (cdbtm.c:673)
因为GP数据库默认的事务id告警是5亿条,停止服务是10亿条,因此达到10亿之后会拒绝服务,应用连接就会出现类似上图红色框中的提示。
原因
查看gp数据库事务告警极限值,以及拒绝服务极限值
--查询数据库拒绝服务极限值
show xid_stop_limit;
--查询数据告警极限值
show xid_warn_limit
目前已经拒绝服务了,因此需要先在服务器上停掉数据库,修改数据库节点的配置
停止数据库
gpstop -M fast
修改配置,找到节点服务器中每一个的postgresql.conf,为其增加
xid_stop_limit=50000000
全部修改完成之后,重启数据库即可
清除
1、检查master数据库年龄
SELECT datname, datfrozenxid ,age(datfrozenxid) FROM pg_database ORDER BY 1 DESC ;
2、---检查segment数据库年龄
SELECT gp_segment_id,datname, age(datfrozenxid) FROM gp_dist_random('pg_database') ORDER BY 3 DESC;
可见还有部分数据库存在的年龄非常的大。因此需要考虑对全库做事务id清理处理
3、针对大量的数据库表进行排序
SELECT c.oid::regclass as tbl,
greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age -- greatest 取最大值
FROM gp_dist_random ('pg_class') c
LEFT JOIN gp_dist_random ('pg_class') t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r') AND
greatest( age( c.relfrozenxid ), age( t.relfrozenxid )) < 891779095 AND
greatest( age( c.relfrozenxid ), age( t.relfrozenxid )) >1000000
ORDER BY age desc
由上图所示,可以根据自己数据库的范围来调整大小值,因为我这边已经处理过一次了,因此现在查询sql已经不算大了。还算正常
4.单表清除
---处理指定表的事务
VACUUM FREEZE tablename
5.批量清除
-将查询出来的结果生成sh可执行脚本
COPY (
SELECT
'echo -n "' || tbl || ' ' || SUM (age) || ' "; psql -d dbname -c " vacuum freeze ' || tbl || ';"'
FROM
(
SELECT
c.gp_segment_id,
c.oid::regclass as tbl,
greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age -- greatest 取最大值
FROM gp_dist_random ('pg_class') c
LEFT JOIN gp_dist_random ('pg_class') t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r') AND
greatest( age( c.relfrozenxid ), age( t.relfrozenxid )) < 891779095 AND
greatest( age( c.relfrozenxid ), age( t.relfrozenxid )) >1000000
ORDER BY age desc
) T
GROUP BY
tbl
ORDER BY
SUM (age) DESC
-- LIMIT 7500 ----如果数据表过多可以根据自己调节
) TO '/home/gpadmin/freeze_vacuum.sh'
上面的sql语句可根据自己数据库的实际进行调整,比如大小范围,条数等,当然生成的sh脚本位置也可以自己指定。
6、去数据库服务器给脚本复权,并执行
可以先查看freeze_vacuum.sh脚本的内容。然后
chmod 777 freeze_vacuum.sh
启动freeze_vacuum.sh脚本,并记录日志存放在process.log文件中
nohup ./freeze_vacuum.sh >process.log 2>&1 &
查看执行情况
ps -ef |grep freeze_vacuum.sh
也可通过日志了解执行进度
tailf process.log
7、定时任务
可以使用dolphinscheduler创建一个sql任务流程,每三个月或者半年执行一次。
注意,上图中对整个库vacuum,会占用大量的IO,并且会花费很多时间,因此在前置sql中配置当前session回话的时间长一些,不然会产生statement_timeout问题。
其他命令
---查询正在执行的sql任务
SELECT
procpid,
start,
now() - start AS lap,
current_query
FROM
(SELECT
backendid,
pg_stat_get_backend_pid(S.backendid) AS procpid,
pg_stat_get_backend_activity_start(S.backendid) AS start,
pg_stat_get_backend_activity(S.backendid) AS current_query
FROM
(SELECT pg_stat_get_backend_idset() AS backendid) AS S
) AS S
WHERE
current_query <> '<IDLE>'
ORDER BY
lap DESC;
--删除正在执行的sql
SELECT pg_terminate_backend(181231);
上面的两个可以在测试的过程中kill掉查询语句,避免出现一些不必要的问题。