每当我运行/部署应用程序时,Heroku postgres DB都会放弃更改

时间:2019-06-09 18:05:58

标签: python heroku heroku-postgres python-telegram-bot

我正在使用python-telegram-bot框架在python中为电报开发一个机器人。

现在,它已作为dyno工作者部署在heroku上,我还使用hobby-dev计划将其链接到Heroku Postgres DB。

问题是,每次我部署应用程序(或在本地重新运行该应用程序时,本地版本也连接到同一数据库),数据库会丢弃该应用程序在运行时对其进行的所有更改。

一个非常奇怪的事实是,即使我添加到表中的行消失了,数据库也会以某种方式跟踪这些更改,例如,“ id”列的“ serial”值考虑了已删除的行(参见下表)。

这是数据库包含的表之一(“ channel”和“ creator”列包含虚假的电报聊天ID,因为它们与案例无关):

id |   question    |          creation          | mode | status |    channel     |  creator  
----+---------------+----------------------------+------+--------+----------------+-----------

  1 | PollQuestion1 | 2019-06-08 13:08:25.240002 | S    | t      | 0001 | 002

  2 | PollQuestion2 | 2019-06-08 13:08:26.830526 | S    | t      | 0001 | 002

  3 | PollQuestion3 | 2019-06-08 23:31:21.574572 | S    | t      | 0001 | 002

  4 | Poll4Question | 2019-06-09 16:35:58.440345 | S    | t      | 0001 | 002

  7 | PQ5           | 2019-06-09 17:42:14.172598 | S    | f      | 0001 | 002

我的应用程序添加了ID为5和6的民意调查,但在重新部署后消失了,但是如您所见,我从 heroku pg:psql 终端手动添加的最后一个民意调查具有ID = 7。

这是一个与db交互的示例函数:

def execute_query(query):
    try:
        res = cur.execute("""{}""".format(query))
        return res
    except psycopg2.Error as e:
        logger.error("Failed executing query {0}: ({1}) {2}".format(query, e.diag.severity, e.diag.message_primary))

def test_command():
    execute_query("insert into poll (question, mode, status, channel, creator) values ('PollT1', 'S', true, '{0}', '{1}')".format(0001, 0002))

如果我随后执行查询

"select * from Poll"

在应用程序中,可以在此处找到第一个查询的结果。

相反,如果我运行相同的

"select * from Poll"
在本地重新部署/重新运行应用程序后,

查询 后, test()函数中包含的查询结果丢失了(如您从在上表中,我执行了两次相同的操作,因此我稍后手动添加的行的ID为7)。

我了解heroku采用的临时文件系统,但是我也读到这不适用于Heroku Postgres,因此DB应该存储我在应用程序中所做的更改,尽管显然不是这样。

注1:在发出“ INSERT”查询和“ UPDATE”查询时,我遇到了这个问题。 注意2:在执行这些操作时,我会不断监视应用程序的控制台输出,并且不会发生任何错误。

有人遇到过同样的问题,并且知道如何解决吗?还是可以指出这个问题的原因?

1 个答案:

答案 0 :(得分:1)

您需要通过调用connection.commit()将更改提交到数据库。

  

commit()

     

将任何未决事务提交到数据库。

     

默认情况下,Psycopg在执行第一个命令之前会打开一个事务:如果未调用commit(),则任何数据操作的效果都会丢失。

假设您有一个表示连接对象的conn变量,则可以在执行查询后立即调用conn.commit()。但是,确保这一点的更安全,更Python化的方法是对连接和游标都使用with语句上下文管理器。

def execute_query(query):
    try:
        with conn:
            with conn.cursor() as cur:
                res = cur.execute("""{}""".format(query))
                return res
    except psycopg2.Error as e:
        logger.error("Failed executing query {0}: ({1}) {2}".format(query, e.diag.severity, e.diag.message_primary))

如果查询成功,此操作将自动调用commit();如果查询失败,则自动调用rollback()