在 PostgreSQL 中,我使用now()
andcurrent_timestamp
函数,我看不出有什么区别:
# SELECT now(), current_timestamp;
now | now
--------------------------------+--------------------------------
04/20/2014 19:44:27.215557 EDT | 04/20/2014 19:44:27.215557 EDT
(1 row)
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?
在尝试访问使用 postgresql 数据库的网站时,甚至在使用 psql 实用程序或 pgadmin3 时,我突然收到此错误。
我的数据库设置为处理 150 个最大连接数:
# SHOW max_connections;
max_connections
-----------------
150
(1 row)
Run Code Online (Sandbox Code Playgroud)
重新启动我的网站所在的 ubuntu 服务器(这实际上是唯一使用连接的东西)后,我看到当前的连接量为 140:
# select count(*) from pg_stat_activity;
count
-------
140
(1 row)
Run Code Online (Sandbox Code Playgroud)
我不明白在重新启动服务器后突然有这么多连接。所以我检查了 postgresql 活动:
# SELECT * FROM pg_stat_activity;
Run Code Online (Sandbox Code Playgroud)
我看到 100 多列具有相同的精确查询,如下所示:
SELECT "reports".* FROM "reports" WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1
Run Code Online (Sandbox Code Playgroud)
更重要的是它们都具有相同的客户端地址(我的 Web 服务器)。
该 Web 服务器使用 ruby on rails,连接池为 50。即使连接池为 50,Passenger 进程/prefork apache 配置是单线程的,因此每个进程不能产生 50 个线程和 50 个数据库连接。更重要的是,这是在系统重新启动后发生的,这将所有用户都从我的 …
我正在阅读 postgresql 管理员手册。某些数据库服务器参数需要重新启动,并且数据库繁忙,您可能需要快速重新启动。有很多事情要做来加速重启:1) 在关闭检查点之前发出一个正常的检查点,2) 将所有脏的 shared_buffers 刷新到磁盘,3) 在关闭之前记录数据库缓存的内容,然后再次预热缓存重启后立即。因此,本书似乎建议:
psql -c "CHECKPOINT"
psql -c "select pg_cache_save('mycache')"
pg_ctl -D datadir -m immediate restart
psql -c "select pg_cache_warm('mycache')"
Run Code Online (Sandbox Code Playgroud)
它还展示了这种方法:
pg_ctl -D datadir restart -m fast
Run Code Online (Sandbox Code Playgroud)
在重新启动经常插入的繁忙数据库时,我应该使用哪一个?以上之一或有更好的方法吗?
我正在使用 ExecutorService,其固定线程池为 50,固定数据库连接池为 50,使用 HikariCP。每个工作线程处理一个数据包(一个“报告”),检查它是否有效(其中每个报告必须有唯一的unit_id、时间、纬度和经度),从连接池中抓取一个db连接,然后将报告插入报告表。唯一性约束是用 postgresql 创建的,称为“reports_uniqueness_index”。当我的音量很大时,我会收到大量以下错误:
org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint "reports_uniqueness_index"
Run Code Online (Sandbox Code Playgroud)
这就是我认为的问题所在。在插入数据库之前,我执行检查以确定表中是否已存在具有相同unit_id、时间、纬度和经度的报告。如果不是,那么报告是有效的,我执行插入。但是,我认为因为我使用并发,所以我有 50 个线程同时检查报告是否有效,并且由于尚未插入它们中的任何一个,每个线程都认为它具有有效的报告以及何时将它们插入同一时刻,也就是 postgresql 引发错误的时候。
我想要一个不会因并发而产生任何延迟的解决方案。我一直试图避免使用同步语句或重入锁,因为数据库插入需要尽快发生。这是这里的插入:
private boolean save(){
Connection conn=null;
Statement stmt=null;
int status=0;
DbConnectionPool dbPool = DbConnectionPool.getInstance();
String sql = = "INSERT INTO reports"
sql += " (unit_id, time, time_secs, latitude, longitude, speed, created_at)";
sql += " values (...)";
try {
conn = dbPool.getConnection();
stmt = conn.createStatement();
status = stmt.executeUpdate(sql);
} catch (SQLException e) {
return false;
} finally {
try { …
Run Code Online (Sandbox Code Playgroud)