Reputation: 370
I have a script which uses up all available connections of the locally running MongoDB and then exists with this error message:
pymongo.errors.AutoReconnect: [Errno 4] Interrupted system call
The error message in /var/log/mongodb/mongod.log is:
[initandlisten] connection refused because too many open connections: 819
The Mongo-Shell gives this output when the script is being invoked:
> db.serverStatus().connections
{ "current" : 1, "available" : 818 } // Script not yet started
> db.serverStatus().connections
{ "current" : 400, "available" : 419 } // Losing connections
> db.serverStatus().connections
{ "current" : 638, "available" : 181 }
> db.serverStatus().connections
{ "current" : 804, "available" : 15 }
> db.serverStatus().connections
{ "current" : 819, "available" : 0 } // Script terminates
> db.serverStatus().connections
{ "current" : 1, "available" : 818 } // Script terminated
I am not able to post the original script, but the following "sanitized" snippet hopefully gives an idea. Basically, I am running all sorts of different queries and updates across several collections.
Most importantly only 5 of 11 database statements will sometimes not release their connection. The other 6 statements will always leave as many free connections as there were before the statement.
mc = pymongo.Connection()
db = mc.database
def available():
""" Return the number of available connections """
return db.command("serverStatus")['connections']['available']
def process():
while True:
# ...
# Connections lost:
conns = available()
coll_a = db.coll_a.find_and_modify(
query={'x': x},
update={'$pop': {'x': -1}},
fields={'x': 1})
if conns > available():
print('Fewer connections')
# ...
# No connections lost:
db.coll_a.update({'x': x}, {'$pullAll': {'x': [x]}})
# ...
# No connections lost:
coll_d = db.coll_d.find_and_modify(
query={'x': x,},
update={'$set': {'x': x}},
fields={'x': 1})
# ...
# No connections lost:
coll_b_cursor = db.coll_b.find({'x': x}, {'x': 1})
# ...
# No connections lost:
coll_e_cursor = db.coll_e.find({'$or': [{'x': x}, {'x': x}]})
# ...
for item in coll_e_cursor:
# No connections lost:
coll_b = db.coll_b.find({'x': x}).count()
# ...
# No connections lost:
coll_b_cursor = db.coll_b.find({'x': x}, {'x': x})
# ...
for x in y:
if x:
# Connections lost:
conns = available()
db.coll_b.update({'x': x}, {'$unset': {'x': 1}})
if conns > available():
print('Fewer connections')
# ...
# Connections lost:
conns = available()
coll_b = db.coll_b.find_and_modify(
query={'x': x},
update={'$set': {'x': x}},
fields={'x': 1},
upsert=True)
if conns > available():
print('Fewer connections')
# ...
# Connections lost:
conns = available()
coll_c_1 = db.coll_c.find_one({'x': x})
coll_c_2 = db.coll_c.find_one({'x': x})
if conns > available():
print('Fewer connections')
# ...
# Connections lost:
conns = available()
db.coll_b.update({'x': x}, {'$unset': {'x': 1}})
if conns > available():
print('Fewer connections')
PyMongo: 2.2.1
MongoDB: 2.0.6
Upvotes: 0
Views: 1065
Reputation: 370
The connections were not lost where it seemed but when.
I overlooked a thread was started somewhere in process():
threading.Thread(target=target, args=(args)).start()
This thread made a database call.
The while loop in process() was fast enough so that many threads were running simultaneously. Using up all available database connections.
Without launching these threads, the number of available database connections remains constant.
Upvotes: 1