【问题标题】:Intermittent sqlite3 binding error on SELECT querySELECT查询上的间歇性sqlite3绑定错误
【发布时间】:2016-03-02 16:09:10
【问题描述】:

我完全被我在 sqlite3 中遇到的间歇性错误所困扰。问题是完全相同的脚本偶尔会运行完成,或者它会在看似随机的 SELECT 语句上失败。由于它不能正确重复,我不知道是我做错了什么还是有错误。我在 mailing list 上看到了一个非常相似的问题,但 Guido van Rossum 只是在其他地方提到了它们,我找不到后续问题。

精简代码:

import sqlite3

conn = sqlite3.connect('c2c_orders.db')
c = conn.cursor()

tracking_nos = [u'1615146623203', u'1614117623187', u'1614174623176', 
                u'1614141623103', u'1614141623101', u'1613102623033', 
                u'1612192622864', u'1612104622842', u'1612109622787', 
                u'1612137622586', u'1612137622583', u'1611191622448', 
                u'1611166622426', u'1610118621895']

for num in tracking_nos:
    print num
    c.execute("SELECT * FROM mw_orders WHERE id=(?)", (num,)) 
    conn.commit()
    db_result = c.fetchall() 

我可以运行一次,然后从打印语句中得到:

1615146623203
1614117623187
1614174623176
1614141623103
1614141623101
1613102623033
...

很好。表中不存在跟踪号,因此它返回一个空列表。重置所有内容并再次运行:

1615146623203
1614117623187
---------------------------------------------------------------------------
InterfaceError                            Traceback (most recent call last)
C:\...path... in <module>()
    113 
    114     orders = check_orders()
--> 115     orderInfo = get_detailed_info(orders)
    116 
    117     end = datetime.datetime.now()

C:\C:\...path... in get_detailed_info(tracking_no)
     63         data_list = get_data.json()
     64 
---> 65         c.execute("SELECT * FROM mw_orders WHERE id=(?)", (num,))
     66         conn.commit()
     67         db_result = c.fetchall()

InterfaceError: Error binding parameter 0 - probably unsupported type.

错误与主脚本有关,因此行不匹配。但我不明白。这可能发生在任何数字上或根本没有发生。据我所知,我正确设置了查询。

这是在 Enthought Canopy 的 Python 2.7 上运行的 sqlite3 版本 2.6.0。有没有人见过这个并且知道如何解决这个问题?提前致谢。

编辑 我的 cmets 中提到的数据库锁在 Windows 重新启动后仍然存在。使用这里描述的软件here我得到以下,显示最后修改日期是在重启之前

事件的顺序更加奇怪。当前错误交替如下。第一次尝试读取数据库将在控制台打印以下内容(在引发错误的查询之前打印跟踪号和类型)

%run "C:\Users\Joshua\Canopy\PCscripts\full_vehicle_routing\dbSyncer2.py"
1608123637974
<type 'unicode'>
1608188637849
<type 'unicode'>
1607105637842
<type 'unicode'>
1607133637841
<type 'unicode'>
---------------------------------------------------------------------------
InterfaceError                            Traceback (most recent call last)
C:\Users\Joshua\Canopy\PCscripts\full_vehicle_routing\dbSyncer2.py in <module>()
    312     removeChecks = remove_all_checks()
    313     orders = check_orders()
--> 314     orderInfo = get_detailed_info(orders)
    315     checkOldOrders = check_old_orders()
    316 

C:\Users\Joshua\Canopy\PCscripts\full_vehicle_routing\dbSyncer2.py in get_detailed_info(tracking_no)
     90         data_list = get_data.json()
     91 
---> 92         c.execute("SELECT * FROM mw_orders WHERE id=(?)", (num,))
     93         conn.commit()
     94         db_result = c.fetchall()

InterfaceError: Error binding parameter 0 - probably unsupported type. 

尝试再次运行它并得到:

C:\Users\Joshua\Canopy\PCscripts\full_vehicle_routing\dbSyncer2.py in remove_all_checks()
     65 
     66 def remove_all_checks():
---> 67     c.execute("UPDATE mw_orders SET is_checked = '0'")
     68     conn.commit()
     69 

OperationalError: database is locked

然后运行相同的脚本再次给出第一个错误。它要么在两者之间进行乒乓操作,要么创建一个持久锁(我假设它是一个完全损坏的数据库。没有其他进程使用这个脚本,我正在开发它作为 Canopy 中的测试,只有这个脚本使用数据库

【问题讨论】:

  • 在这种情况下显示num的值和类型。
  • @CL。这是错误上方打印的错误:1614117623187(在 SELECT 查询失败之前打印)。我认为parameter 0 指的是num 而不是表中的东西(*)是正确的?现在我无法在while true 循环中获取它,所以我认为我在不知道的情况下对数据库做了一些事情......这意味着我无法检查类型。我现在要为我的新想法添加一个编辑,因为这可能是自动提交失败的问题。
  • @CL。我已经在底部进行了编辑,如果您能看一下,将不胜感激。我即将开始自己构建一个测试用例,但我可能会偏离目标?
  • @CL。确认即使失败,这些数字也会以 unicode 字符串的形式出现。 id 也存储为字符串。当我问这个问题时,从我所在的位置继续前进;脚本的第一次运行现在成功地将 JSON 字符串中的所有条目写入数据库。再次运行应该从表中返回条目的脚本在随机数上失败。不仅如此,它现在还锁定了数据库,即使重新启动也无法解锁它(Windows 7 显示它是我自己的脚本,即使在重新启动后也保持锁定)
  • 重启后任何进程都不可能存活。这听起来好像您的脚本在您不期望的情况下运行,可能多次运行。

标签: python sqlite


【解决方案1】:

您在 select 与其 fetch 之间的提交不应该存在。

可以肯定的是,您可以尝试在删除提交后通过 try catch 控制发生的情况:

for num in tracking_nos:
    print num
    try:
        c.execute("SELECT * FROM mw_orders WHERE id=(?)", (num,)) 
        db_result = c.fetchall()
    except Exception as e:
        print "*** ERROR *** ", e, "  reading >", num, "<", type(num)
        # con.close()  # optionally depending on your higher level logic
        raise e

【讨论】:

  • 这将需要我一段时间来测试这个抱歉,因为现在我不能让它再次失败!我认为建议是在打印队列没有刷新以在失败的查询中显示最新的numtype 的情况下?我现在想知道我正在查询的服务器上是否存在某种类型问题,因为要正确调查此问题非常困难。
  • 我很遗憾地说,经过数百次循环后,我现在无法重复错误,但我没有改变任何根本性的东西。这个问题持续了4天没有任何活动的原因是这也发生过。为了安心,我想进一步深入研究,也许它会回来。感谢您删除提交的建议,我确实摆脱了它。根据您的经验,这可能是导致行为不稳定的原因吗?
  • @roganjosh 我并不是真正的 SQLite 专家,我只将它用于简单的操作。那里的提交确实很糟糕,但我不能说这是否足以导致不稳定。如果您删除它并且从那时起它一直有效,也许......无论如何,我已经改写了我的帖子以使其看起来像一个答案
  • 好的,谢谢。直觉上它并不觉得这将是根本原因,但它仍然无法解释。我将接受并暂时关闭此内容,因为显然我没有足够的信息让我们任何人知道出了什么问题。如果我得到更接近的结果并且您的 try/except/ 在该事件中仍然存在,我将重新提出另一个问题 :)
【解决方案2】:

尝试检查连接隔离级别:https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.isolation_level

'获取或设置当前隔离级别。无自动提交模式或 “延期”、“立即”或“独家”之一。请参阅控制部分 交易以获得更详细的解释。'

--> 试试“独家”

【讨论】:

  • 感谢您的建议,但它的行为方式完全相同:(
猜你喜欢
  • 1970-01-01
  • 2022-07-19
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 2023-03-07
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多