python postgres游标时间戳问题

我对事务数据库有点新,并且遇到了我想要了解的问题.

我创建了一个简单的演示,其中数据库连接存储在cherrypy创建的5个线程中.我有一个方法,显示存储在数据库中的时间戳表和一个添加新的时间戳记记录的按钮.

该表有2个字段,一个用于python传递的datetime.datetime.now()时间戳,另一个用于数据库时间戳设置为默认NOW().


CREATE TABLE test (given_time timestamp,default_time timestamp DEFAULT NOW());

我有2个与数据库交互的方法.第一个将创建一个新游标,插入一个新的given_timestamp,提交游标,然后返回索引页面.第二种方法将创建一个新游标,选择10个最新时间戳并将其返回给调用者.


import sys
import datetime
import psycopg2
import cherrypy

def connect(thread_index): 
    # Create a connection and store it in the current thread 
    cherrypy.thread_data.db = psycopg2.connect('dbname=timestamps')

# Tell CherryPy to call "connect" for each thread,when it starts up
cherrypy.engine.subscribe('start_thread',connect)

class Root:
    @cherrypy.expose
    def index(self): 
        html = []
        html.append("

我希望given_time和default_time时间戳只相隔几微秒.但是我得到了一些奇怪的行为.如果我每隔几秒钟添加一次时间戳,则default_time与given_time相差不到几微秒,但通常比之前的given_time减去几微秒.

Given Time                  Default Time
2009-03-18 09:31:30.725017  2009-03-18 09:31:25.218871
2009-03-18 09:31:25.198022  2009-03-18 09:31:17.642010
2009-03-18 09:31:17.622439  2009-03-18 09:31:08.266720
2009-03-18 09:31:08.246084  2009-03-18 09:31:01.970120
2009-03-18 09:31:01.950780  2009-03-18 09:30:53.571090
2009-03-18 09:30:53.550952  2009-03-18 09:30:47.260795
2009-03-18 09:30:47.239150  2009-03-18 09:30:41.177318
2009-03-18 09:30:41.151950  2009-03-18 09:30:36.005037
2009-03-18 09:30:35.983541  2009-03-18 09:30:31.666679
2009-03-18 09:30:31.649717  2009-03-18 09:30:28.319693

然而,如果我每分钟添加一个新的时间戳,则given_time和default_time都只是按预期的几微秒关闭.但是,在提交第6个时间戳(线程数1)之后,default_time与第一个给定时间戳相距几微秒.

Given Time                  Default Time
2009-03-18 09:38:15.906788  2009-03-18 09:33:58.839075
2009-03-18 09:37:19.520227  2009-03-18 09:37:19.520293
2009-03-18 09:36:04.744987  2009-03-18 09:36:04.745039
2009-03-18 09:35:05.958962  2009-03-18 09:35:05.959053
2009-03-18 09:34:10.961227  2009-03-18 09:34:10.961298
2009-03-18 09:33:58.822138  2009-03-18 09:33:55.423485

即使我在每次使用后显式关闭游标,看起来前一个游标仍然被重用.如果我在完成光标并每次创建一个新光标后关闭光标,那怎么可能呢?有人可以解释一下这里发生了什么吗?

接近答案:

我已经将一个cursor.connection.commit()添加到了get_timestamps方法,现在它为我提供了带有时间戳的准确数据.任何人都可以解释为什么我需要调用cursor.connection.commit()当我所做的只是一个选择?我猜每次我得到一个游标,一个事务就开始了(或者继续它提交的现有事务单元).有没有更好的方法来做到这一点,或者每次我得到一个光标时,无论我对该光标做什么,我都会坚持提交?

最佳答案
要解决您最近编辑提出的问题:

在PostgreSQL中,NOW()不是当前时间,而是当前事务开始时的时间. Psycopg2可能会隐式为您启动一个事务,并且由于事务永远不会被关闭(通过提交或其他方式),因此时间戳会“卡住”并变得陈旧.

可能的修复:

>经常提交(如果你只做SELECT,那就很傻)
>设置Psycopg2以使用不同的行为来自动创建事务(可能很难做到正确,并会影响应用程序的其他部分)
>使用不同的时间戳函数,例如statement_timestamp()(不符合SQL标准,但在这种情况下非常完美)

the manual,section 9.9.4开始,重点增加:

PostgreSQL provides a number of
functions that return values related
to the current date and time. These
SQL-standard functions all return
values based on the start time of the
current transaction:

  • CURRENT_DATE
  • CURRENT_TIME
  • CURRENT_TIMESTAMP
  • CURRENT_TIME(precision)
  • CURRENT_TIMESTAMP(precision)
  • LOCALTIME LOCALTIMESTAMP
  • LOCALTIME(precision)
  • LOCALTIMESTAMP(precision)

CURRENT_TIME and CURRENT_TIMESTAMP
deliver values with time zone;
LOCALTIME and LOCALTIMESTAMP
deliver values without time zone.

CURRENT_TIME,CURRENT_TIMESTAMP,
LOCALTIME,and LOCALTIMESTAMP can
optionally be given a precision
parameter,which causes the result to
be rounded to that many fractional
digits in the seconds field. Without a
precision parameter,the result is
given to the full available precision.

Since these functions return the
start time of the current transaction,
their values do not change during the
transaction
. This is considered a
feature: the intent is to allow a
single transaction to have a
consistent notion of the “current”
time,so that multiple modifications
within the same transaction bear the
same time stamp.

Note: Other database systems might advance these values more frequently.

PostgreSQL also provides functions
that return the start time of the
current statement,as well as the
actual current time at the instant the
function is called. The complete list
of non-SQL-standard time functions is:

  • now()
  • transaction_timestamp()
  • statement_timestamp()
  • clock_timestamp()
  • timeofday()

now() is a traditional PostgreSQL
equivalent to CURRENT_TIMESTAMP.
transaction_timestamp() is likewise
equivalent to CURRENT_TIMESTAMP,but
is named to clearly reflect what it
returns. statement_timestamp()
returns the start time of the current
statement (more specifically,the time
of receipt of the latest command
message from the client).
statement_timestamp() and
transaction_timestamp() return the
same value during the first command of
a transaction,but might differ during
subsequent commands.
clock_timestamp() returns the actual
current time,and therefore its value
changes even within a single SQL
command. timeofday() is a historical
PostgreSQL function. Like
clock_timestamp(),it returns the
actual current time,but as a
formatted text string rather than a
timestamp with time zone value.

相关文章

使用OpenCV实现视频去抖 整体步骤: 设置输入输出视频 寻找帧...
前言 对中文标题使用余弦相似度算法和编辑距离相似度分析进行...
前言 之前尝试写过一个爬虫,那时对网页请求还不够熟练,用的...
前言 本文使用Python实现了PCA算法,并使用ORL人脸数据集进行...
前言 使用opencv对图像进行操作,要求:(1)定位银行票据的...
天气预报API 功能 从中国天气网抓取数据返回1-7天的天气数据...