postgresql 因存在长事务而导致vacuum失效

一.问题

        在数据库中查询某表时,已经走索引了,但是速度仍然慢。查询后发现该表占用磁盘较大,但是数据条数并不多,经查询后发现死元组过多(

SELECT n_dead_tup 
FROM pg_stat_user_tables 
WHERE relname = 'table name';

)。使用vacuum和vacuum full 命令回收表空间后,死元组并不能被删除。

二.原因

        vacuum命令会回收重用那些对所有事务不可见的死亡元组。当存在事务对某表中的死元组可见的情况下,vacuum就会失效,最终导致表膨胀。

       1.某长事务对表进行(如:insert、delete、update、alter table等操作并且未提交,那么vacuum操作会失效);因为此时的死元组对该事务是可见的,尽管对其他事务不可见,但仍然无法删除死元组。

       2.某长事务不进行任何操作或者只进行简单的select查询操作,此时该长事务不会影响到vacuum操作,可以正常删除死元组。因为此时被回收表的死元组对于长事务是不可见的,其他事务在进行更改操作时,数据库会基于MVCC机制为该长事务维护一个更改前的数据版本。

三.解决方法

       kill掉长时间不活跃的事务(idle_in_transaction)。

      1.设置合理的 idle_in_transaction_session_timeout 参数值;

      2.手动查询到长事务,并kill;

--在服务器中查询长事务id -- oldest xmin
VACUUM verbose tablename;

--通过长事务id查询 pid
SELECT *
FROM pg_stat_activity 
WHERE backend_xmin = 'oldest xmin'
;

--杀死进程
--强杀 向后台发送sigterm信号,关闭当前后台进程,需要有超级用户权限,超级用户可以关闭所有后台进程,事务回滚
select pg_terminate_backend(pid)
;

--表回收
vacuum full tablename
;

至此,vacuum 命令失效的问题得到解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值