Sah*_*wal 14 java postgresql performance hibernate postgresql-9.3
有一张桌子,有200行.但是显示那里的实时元组的数量超过了(大约60K).
select count(*) from subscriber_offset_manager;
 count 
-------
   200
(1 row)
 SELECT schemaname,relname,n_live_tup,n_dead_tup FROM pg_stat_user_tables  where relname='subscriber_offset_manager' ORDER BY n_dead_tup
;
 schemaname |          relname          | n_live_tup | n_dead_tup 
------------+---------------------------+------------+------------
 public     | subscriber_offset_manager |      61453 |          5
(1 row)
但是从pg_stat_activity和pg_locks可以看出,我们无法跟踪任何打开的连接.
SELECT query, state,locktype,mode
FROM pg_locks
JOIN pg_stat_activity
  USING (pid)
WHERE relation::regclass = 'subscriber_offset_manager'::regclass
  ;
 query | state | locktype | mode 
-------+-------+----------+------
(0 rows)
我也试过这张桌子上的全真空,下面是结果:
这是输出.
vacuum FULL VERBOSE ANALYZE subscriber_offset_manager;
INFO:  vacuuming "public.subscriber_offset_manager"
INFO:  "subscriber_offset_manager": found 0 removable, 67920 nonremovable row versions in 714 pages
DETAIL:  67720 dead row versions cannot be removed yet.
CPU 0.01s/0.06u sec elapsed 0.13 sec.
INFO:  analyzing "public.subscriber_offset_manager"
INFO:  "subscriber_offset_manager": scanned 710 of 710 pages, containing 200 live rows and 67720 dead rows; 200 rows in sample, 200 estimated total rows
VACUUM
 SELECT schemaname,relname,n_live_tup,n_dead_tup FROM pg_stat_user_tables  where relname='subscriber_offset_manager' ORDER BY n_dead_tup
;
 schemaname |          relname          | n_live_tup | n_dead_tup 
------------+---------------------------+------------+------------
 public     | subscriber_offset_manager |        200 |      67749
10秒后
SELECT schemaname,relname,n_live_tup,n_dead_tup FROM pg_stat_user_tables  where relname='subscriber_offset_manager' ORDER BY n_dead_tup
;
 schemaname |          relname          | n_live_tup | n_dead_tup 
------------+---------------------------+------------+------------
 public     | subscriber_offset_manager |      68325 |        132
我们的App如何查询此表.
我们的应用程序通常选择一些行并根据一些业务计算更新行.
选择查询 - 根据某些ID选择
select*from subscriber_offset_manager,其中shard_id = 1;
更新查询 - 更新此选定分片ID的其他一些列
大约20个线程并行执行此操作,一个线程仅在一行上工作.
另一个有趣的观察: - 当我停止我的Java应用程序,然后完全真空,它工作正常(行数和实时元组变得相等).因此,如果我们从Java应用程序中连续选择和更新,则会出现问题.-
问题/发行
这些活元组有时会去死元组,并且经过一段时间再次生存.
由于上述行为,从表中选择花费时间和增加服务器上的负载,因为有很多活/死的..
毕竟可能存在锁,您的查询可能会产生误导:
\n\nSELECT query, state,locktype,mode\nFROM pg_locks\nJOIN pg_stat_activity USING (pid)\nWHERE relation = \'subscriber_offset_manager\'::regclass\npg_locks.pid可以为 NULL,那么连接将消除行。Postgres 9.3 的手册:
\n\n\n持有或等待此锁的服务器进程的进程 ID,如果该锁由准备好的事务持有,则为 null
\n
大胆强调我的。(第 10 页仍然相同。)
\n\n通过简单的查询你能得到什么吗?
\n\nSELECT * FROM pg_locks\nWHERE relation = \'subscriber_offset_manager\'::regclass;\n这可以解释为什么VACUUM抱怨:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nDETAIL: 67720 dead row versions cannot be removed yet.\n
反过来,这会指出应用程序逻辑/查询中的问题,锁定比必要的更多的行。
\n\n我的第一个想法是长时间运行的事务,即使是一个简单的事务SELECT(获取低级ACCESS SHARE锁)也可能阻止VACUUM其工作。20 个并行线程可能会连锁并锁定VACUUM。让您的事务(及其锁)尽可能简短。并确保您的查询已优化并且不会锁定不必要的行。
还有一件事需要注意:事务隔离级别SERIALIZABLE或REPEATABLE READ使VACUUM清理变得更加困难。默认READ COMMITTED模式限制较少,但是VACUUM仍然可以按照讨论的方式进行阻止。
有关的:
\n\n我有问题吗?。
为了理解该问题,请考虑以下流程:
线程1-
并行运行的Thread-1类型的许多线程。
线程2-
临时解决方案 -如果我使用pg_cancel_backend关闭了Thread-2进行的所有连接,则清理工作开始。
此外,我们已经多次重现该问题,并尝试了此解决方案,并且该解决方案有效。
现在,有以下疑问仍未得到解决。
一些更令人惊讶的观察:
@Erwin Brandstetter和@Laurenz Albe,如果您知道存在与postgres / jdbc相关的错误。
| 归档时间: | 
 | 
| 查看次数: | 2310 次 | 
| 最近记录: |