Sqlite3错误:Recursive use of cursors not allowed 的解决方案

【感悟】

写完这篇日志后,有调了一段时间程序,又有了一点心得分享下:

一)爬稳定的数(dong)据(xi)最好存储下来,特别是数据库在国外的那种,下载时间成本太高昂了,存起来再处理,会节约很多时间;

二)对于python使用多线程写数据到sqlite数据库的做法绝对是浪费感情,是扯淡的行为,一个词叫“大材小用”,单线程足够了。

三)写数据到数据库中commit的次数最好减少,可以10000条insert后commit,当然这取决于事务本身和其他因素,我这里可以提升一倍的速度。

四)回到爬的数据上,文本形式存储对于散户使用是最优的,处理速度快,格式定义好,正则等功能完胜sqlite。

------------------------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------------------------------------------

【问题情境】

最近手闲,想写一个简单的批量下载网页的python工具。当然爬虫的轻量级框架scrapy以前用过,还不错。因为这次需求很简单,就直接人肉搞了。结果各种问题就出来了。

其中的思路是,多线程数据库存储这些网页,也方便之后数据处理。但是跑多线程时,脚本经常死掉。开了50个线程,基本出现的错误提示就是"Recursive use of cursors not allowed".

问题分析】

数据库跑多线程的故事吧,一般都是事务没提交无法保证原子性的问题。问题解决方案可直接看下面的【问题解决】部分。

检查了第一遍:

问题1:

发现有个查询语句select没有提交,commit了一下。

分析1:

这里感觉没有什么问题,因为查询没有改变数据库所以不提交也一样。

跑一遍:

似乎错误提示少了一些。此时,我insert数据的sleep时间是1sec.试了几遍,还是中途崩掉。

检查第二遍:

问题2:

缩短insert的sleep时间,问题更严重了。很快姐崩了。

分析2:

应该是insert频繁导致的sql语句冲突概率增加。总感觉这里有问题,就差了下资料,果然是sqlite3多线程的时候有猫腻。于是,在每个提交的位置都增加了线程锁,增强同步效果。

跑了一遍:

错误提示"Recursive use of cursors not allowed"没有再出现。


【解决方案】

加锁,提交。

lock = threading.Lock()

def Func(host,cursor,db):
    try:
        lock.acquire(True)
        res = cursor.execute('''...''',(host,))
        # do something
    finally:
        lock.release()

【其他】

python的sqlite3使用多线程的参数check_same_thread是需要的:

self.conn = sqlite3.connect(dbname, check_same_thread=False)


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值