V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Va1n3R
V2EX  ›  Python

CURDboy 问问各位,mysql 怎么多线程 insert 数据啊...

  •  
  •   Va1n3R · Dec 19, 2017 · 4123 views
    This topic created in 3051 days ago, the information mentioned may be changed or developed.

    python3 写了个爬虫。
    多线程爬取数据写入数据库
    一开始使用的是 sqllite3,一直提示 database is blocked,后来发现 sqllite 不支持多线程读写
    然后谷歌搜了一下,看到了别人推荐使用 mysql 来做这种任务...我只会基础的 CURD 操作,用了简单的多线程来操作,然而 mysql 貌似也不能直接多线程插入数据,stackoverflow 里面的老哥们说是需要建立连接池...头疼,之前只接触过基础的操作,请各位 V2er 赐教
    python3 代码:

    def getExin():
        while not Q.empty():
            i = Q.get()
            .*
            try:
                .*
            except :
                continue
            try:
                c.execute("INSERT INTO exin (username, password) \
                      VALUES (%s,'%s')" % (username, password))
                conn.commit()
            except:
                pass
    
    
    for i in range(0, 99475):
        if len(str(i)) < 5:
            i = (5 - len(str(i))) * "0" + str(i)
        Q.put(i)
    
    threads = []
    
    conn = connect(user='root', password='root', database='test')
    c = conn.cursor()
    for i in range(800):
        x = threading.Thread(target=getExin,args=())
        threads.append(x)
    for t in threads:
        t.start()
    c.close()
    print("All done")
    
    24 replies    2017-12-20 16:20:48 +08:00
    misaka19000
        1
    misaka19000  
       Dec 19, 2017
    一个线程对应一个链接就行了
    Va1n3R
        3
    Va1n3R  
    OP
       Dec 19, 2017 via iPhone
    @misaka19000 尝试过会提示连接不上,我这里是 1000 线程
    zeraba
        4
    zeraba  
       Dec 19, 2017 via Android
    executemany 不行么 是什么场景非要多线程多个事务去写入哪
    Va1n3R
        5
    Va1n3R  
    OP
       Dec 19, 2017
    @zeraba 访问一次目标获取一次信息,然后写入数据库,就这么简单的逻辑,但是单线程太慢了...
    zeraba
        6
    zeraba  
       Dec 19, 2017 via Android
    @Va1n3R 要么一次一次写 redis 要么把取回的数据先存成 list 或者 tuple 到了一定的量再批量插入 mysql 你这么搞 太费资源了
    Va1n3R
        7
    Va1n3R  
    OP
       Dec 19, 2017
    @zeraba 资源不是问题,只是不想把简单问题复杂化,谢谢老哥啦
    Cooky
        8
    Cooky  
       Dec 19, 2017 via Android
    你这只是一个连接多线程使用吧
    kiwi95
        9
    kiwi95  
       Dec 19, 2017
    你现在 Q 是共享的,那 Q 的 get,put 是不是阻塞的?然后多个线程也是操作一个连接作数据插入,这样多线程有什么意义呢,除非你的数据准备阶段占时间开销的大头,否则这样并不能提升速度
    likuku
        10
    likuku  
       Dec 19, 2017
    老生常谈提示下:得用 InnoDB
    Va1n3R
        11
    Va1n3R  
    OP
       Dec 19, 2017
    @Cooky 我尝试过多线程每个都链接一次,但是 mysql 会拒绝我的访问....我开了 800~1000 的线程
    Va1n3R
        12
    Va1n3R  
    OP
       Dec 19, 2017
    @kiwi95 Q 是 queue,应该不会阻塞吧,速度提升确实肉眼可见啊...
    Sanko
        13
    Sanko  
       Dec 19, 2017 via Android
    executemany 应该不慢吧
    Va1n3R
        14
    Va1n3R  
    OP
       Dec 19, 2017
    @Sanko
    @zeraba 数据量挺大的,直接放入字典,我怕内存会爆啊
    Cooky
        15
    Cooky  
       Dec 19, 2017 via Android
    @Va1n3R 看看 MySQL 默认最大连接数多少,改下配置
    HanSonJ
        16
    HanSonJ  
       Dec 20, 2017
    这种情况,批量 insert 最佳

    插入速度优化上百倍
    billlee
        17
    billlee  
       Dec 20, 2017
    你如果不批量插入,开再多线程,HDD 上一秒也只能提交 100 个事务。
    jimzhong
        18
    jimzhong  
       Dec 20, 2017
    你开多线程获得的性能提升未必有批量插入大。
    huhujin
        19
    huhujin  
       Dec 20, 2017
    我瞎比说说:
    for i in range(800):
    x = threading.Thread(target=getExin,args=())
    t.setDaemon(True)
    x.start()
    2ME
        20
    2ME  
       Dec 20, 2017
    不懂 py .. 不过你这么搞肯定有问题 线程开太高 mysql 最大连接数会有问题 就算连得上 你 IO 还是会有问题 和#18 说的一样 你开多线程不一定有拼接 sql 批量插入来的实在
    catinred
        21
    catinred  
       Dec 20, 2017
    中间用个队列把数据存起来 然后起个线程批量插入就好了
    exiaohao
        22
    exiaohao  
       Dec 20, 2017
    这种事吧,celery 就好啦 gevent 开起来妈妈再也不用担心并发上不去了
    搞 thread 多麻烦
    Va1n3R
        23
    Va1n3R  
    OP
       Dec 20, 2017
    @2ME 已经采用了 executemany 啦
    Va1n3R
        24
    Va1n3R  
    OP
       Dec 20, 2017
    @exiaohao 之前没有写过协程、异步。昨晚看了一下,启发很大
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1863 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 75ms · UTC 16:18 · PVG 00:18 · LAX 09:18 · JFK 12:18
    ♥ Do have faith in what you're doing.