今天使用 pymongo 测试一个小功能的时候,运行代码,发现代码卡在数据库查询的语句了,然后执行不下去了,直到超时才抛异常,然后再调用一次又正常了,之后都正常,没有再出现这个问题了。
但是,在正常的第一次哪里,打印出了一句 warnning:
.../site-packages/pymongo/topology.py:75: UserWarning: MongoClient opened before fork. Create MongoClient with connect=False, or create client after forking. See PyMongo's documentation for details: http://api.mongodb.org/python/current/faq.html#using-pymongo-with-multiprocessing>
"MongoClient opened before fork. Create MongoClient "
于是乎,我就打开了这个url:http://api.mongodb.org/python/current/faq.html#using-pymongo-with-multiprocessing
然后就看到了这段话:
图 1:PyMongo Multiprocess |
其实就是说在使用 multiprocessing 的同时使用 PyMongo 库:
- 要么在创建新进程的时候给 MongoClient 加上 connect=False 参数
- 或者在子进程里面创建 MongoClient
不然就有可能导致死锁。
原因是 CPython 在调用 getaddrinfo() 之前会请求一个锁,如果在 fork 进程的时候主进程获得这个锁,那么就会可能发生死锁。所以,在这种情况下 PyMongo 会打印一个 Warning 的提醒。
Okay,最终在初始化的地方我加上了 connect=False
的参数这个问题就没有出现了。加上这个参数的意思是:
- 如果没有这个参数,数据库连接会在创建对象的时候创建连接
- 如果加上这个参数,数据库会在第一次调用函数的创建连接
所以,这里就防止死锁的问题了。