执行时:
select * from pg_stat_activity where state ~ 'idle in transact'
在事务处理中,状态为“空闲”的行数不合适。他们中的一些人闲置了几天。其中大多数都是从一个服务类(Hibernate 5.1.0.Final,Guice 4.1.0)执行的简单select
查询:
public class FirebaseServiceImpl implements FirebaseService {
@Inject
private Provider<FirebaseKeyDAO> firebaseKeyDAO;
@Override
public void sendNotification(User recipient) {
List<FirebaseKey> firebaseKeys = firebaseKeyDAO.get().findByUserId(recipient.getId());
final ExecutorService notificationsPool = Executors.newFixedThreadPool(3);
for (FirebaseKey firebaseKey : firebaseKeys)
notificationsPool.execute(new Runnable() {
@Override
public void run() {
sendNotification(new FirebaseNotification(firebaseKey.getFirebaseKey(), "example");
}
});
notificationsPool.shutdown();
}
}
DAO方法:
@Override
@SuppressWarnings("unchecked")
public List<FirebaseKey> findByUserId(Long userId) {
Criteria criteria = getSession().createCriteria(type);
criteria.add(Restrictions.eq("userId", userId));
return criteria.list();
}
为什么会这样?怎么避免这个?
更新
当我在单独的线程中使用Guice Provider exampleDAO.get()
时,不会提交事务:
@Inject
Provider<ExampleDAO> exampleDAO;
答案 0 :(得分:2)
当您使用pgbouncer或其他使用pool_mode = transaction的pooler /会话管理器时,通常会发生这种情况。例如,当客户打开一个交易并持有它时,不提交或回滚。检查您是否在查询列中看到DISCARD ALL
- 如果您这样做,because pooler必须丢弃共享会话计划,序列,解除分配语句等,以避免混合池中不同会话的那些。 / p>
另一方面,任何&#34;正常&#34; transaction提供相同的idle in transaction
,例如:
2>select now(),pg_backend_pid();
now | pg_backend_pid
----------------------------------+----------------
2017-05-05 16:53:01.867444+05:30 | 26500
(1 row)
如果我们检查其状态,我们会看到正统的idle
:
t=# select query,state from pg_stat_activity where pid = 26500;
query | state
--------------------------------+-------
select now(),pg_backend_pid(); | idle
(1 row)
现在我们在session 2 >
开始交易:
2 - ;开始;
BEGIN
2>select now(),pg_backend_pid();
now | pg_backend_pid
----------------------------------+----------------
2017-05-05 16:54:15.856306+05:30 | 26500
(1 row)
并检查pg_stat_statements
获得:
t=# select query,state from pg_stat_activity where pid = 26500;
query | state
--------------------------------+---------------------
select now(),pg_backend_pid(); | idle in transaction
(1 row)
它将保持这种方式,直到语句超时或事务结束:
2>end;
COMMIT
t=# select query,state from pg_stat_activity where pid = 26500;
query | state
-------+-------
end; | idle
(1 row)
因此它很常见且没问题。如果要避免连接会话,则必须断开客户端连接。但是postgres中的连接很昂贵,所以通常人们会尝试重用与池的现有连接,因此这些状态出现在pg_stat_activity