【问题标题】:Using Postgres in a web app: "transaction aborted" errors在 Web 应用程序中使用 Postgres:“事务中止”错误
【发布时间】:2010-02-05 17:46:48
【问题描述】:

最近,出于性能原因(我需要 PostGIS 提供的功能),我将正在开发的 Web 应用程序从 MySQL 迁移到 PostgreSQL。现在经常遇到如下错误:

current transaction is aborted, commands ignored until end of transaction block

服务器应用程序使用 mod_python。错误发生在招呼功能(即为该特定客户端创建新会话的功能)中。下面是一段适当的代码(异常发生在调用 sessionAppId 的行:

def hello(req):
req.content_type = "text/json"
req.headers_out.add('Cache-Control', "no-store, no-cache, must-revalidate")
req.headers_out.add('Pragma', "no-cache")
req.headers_out.add('Expires', "-1")
instance = req.hostname.split(".")[0]

cookieSecret = '....' # whatever :-)
receivedCookies = Cookie.get_cookies(req, Cookie.SignedCookie, secret = cookieSecret)
sessionList = receivedCookies.get('sessions', None)
sessionId = str(uuid.uuid4())
if sessionList:
    if type(sessionList) is not Cookie.SignedCookie:
        return "{status: 'error', errno:1, errmsg:'Permission denied.'}"
    else:
        sessionList = sessionList.value.split(",")
        for x in sessionList[:]:
            revisionCookie = receivedCookies.get('rev_' + str(sessionAppId(x, instance)), None)
            # more processing here....
# .....
cursors[instance].execute("lock revision, app, timeout IN SHARE MODE")
cursors[instance].execute("insert into app (type, active, active_revision, contents, z) values ('session', true, %s, %s, 0) returning id", (cRevision, sessionId))
sAppId = cursors[instance].fetchone()[0]
cursors[instance].execute("insert into revision (app_id, type) values (%s, 'active')", (sAppId,))
cursors[instance].execute("insert into timeout (app_id, last_seen) values (%s, now())", (sAppId,))
connections[instance].commit()
# .....

这里是 sessionAppId 本身:

def sessionAppId(sessionId, instance):
cursors[instance].execute("select id from app where type='session' and contents = %s", (sessionId, ))
row = cursors[instance].fetchone()
if row == None:
    return 0
else:
    return row[0]

一些澄清和其他问题:

  1. cursors[instance] 和 connections[instance] 是数据库连接和在此域名上服务的 Web 应用实例的光标。 IE。同一台服务器为 example1.com 和 example2.com 提供服务,并使用这些字典根据请求所针对的服务器名称调用适当的数据库。
  2. 我真的需要在 hello() 函数中锁定表吗?
  3. 需要 hello() 中的大部分代码来为每个浏览器选项卡维护一个单独的会话。我找不到仅使用 cookie 的方法,因为打开网站的浏览器选项卡共享 cookie 池。有更好的方法吗?

非常感谢。

【问题讨论】:

    标签: python postgresql concurrency


    【解决方案1】:

    该错误是由先前的错误引起的。看这段代码:

    >>> import psycopg2
    >>> conn = psycopg2.connect('')
    >>> cur = conn.cursor()
    >>> cur.execute('select current _date')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    psycopg2.ProgrammingError: syntax error at or near "_date"
    LINE 1: select current _date
                           ^
    
    >>> cur.execute('select current_date')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block
    
    >>> conn.rollback()
    >>> cur.execute('select current_date')
    >>> cur.fetchall()
    [(datetime.date(2010, 2, 5),)]
    >>> 
    

    如果您熟悉twisted,请查看twisted.enterprise.adbapi 了解如何处理游标的示例。基本上你应该总是提交或回滚你的游标:

    try:
        cur.execute("...")
        cur.fetchall()
        cur.close()
        connection.commit()
    except:
        connection.rollback()
    

    【讨论】:

    • 感谢您的提示。我现在将修复我的代码,看看它是否有帮助
    • 到目前为止,似乎正确提交和回滚所有操作,包括那些只涉及从表中选择的操作,已经解决了这个问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-10-21
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多