Ensure that .executeQuery and .cancel are implemented
The only way we've found so far to cancel a long running query is to use db.currentOp()
which lists all active (pending) operations (i.e. that are still running on the MongoDB server), then use db.killOp(opid)
for every opid returned by the previous command.
Some filters can be applied on currentOp()
, of course (e.g. consider only the objects that have the property "op" : "query" set), but there is no guarantee that only the operation associated to the current statement / user is cancelled (killed) .
Do you have any suggestions on this feature?
The DBCursor class has a close() method that sends an OP_KILL_CURSORS message, but this doesn't work for pending queries (because the iterator field, DBCursor._it
is not yet assigned). Probably this message should be used only to release resources, not to cancel pending operations.
The MongoDB Shell cancels pending queries ( on CTRL + C ) by filtering the inprog array by the "client" property (see the C++ source-code) . However, the MongoDB Java Driver doesn't provide access (API) to the socket (client port etc) created during network communication.
I guess there is no safe way to implement the cancel() feature (i.e. kill only the owned in-progress operations) using the Java Driver.
The MongoDB Shell cancels pending queries ( on CTRL + C ) by filtering the inprog array by the "client" property (see the C++ source-code) . However, the MongoDB Java Driver doesn't provide access (API) to the socket (client port etc) created during network communication.
I guess there is no safe way to implement the cancel() feature (i.e. kill only the owned in-progress operations) using the Java Driver.
After reading some online docs and discussing this with Sachin, we think the following approach may work.
First, the Mongo object maintains an internal pool of connections to the database with a default pool size of 10. If we set the connection pool size to 1, then there is only one connection per Mongo object.
http://www.littlelostmanuals.com/2011/11/increasing-mongodb-connection-pool.html
When you run the mongo command "whatsmyuri", the connection ID is returned.
db.runCommand("whatsmyuri");
returns:
{ "you" : "127.0.0.1:54937", "ok" : 1 }
Using the connection ID, you can get the "opid" from db.currentOp().
After reading some online docs and discussing this with Sachin, we think the following approach may work.
First, the Mongo object maintains an internal pool of connections to the database with a default pool size of 10. If we set the connection pool size to 1, then there is only one connection per Mongo object.
http://www.littlelostmanuals.com/2011/11/increasing-mongodb-connection-pool.html
When you run the mongo command "whatsmyuri", the connection ID is returned.
db.runCommand("whatsmyuri");
returns:
{ "you" : "127.0.0.1:54937", "ok" : 1 }
Using the connection ID, you can get the "opid" from db.currentOp().
Thank you for your input. Implemented it as suggested. There are few challenges worth mentioning here:
MongoStatement.cancel()
(to query "whatsmyuri", currentOp() and killOp() ) because it would not be executed instantly but wait until the server connection is released from the connection pool (i.e. after the long running query has finished); DB.authenticate(user, password)
on the new DB instance created at previous step. In order to perform this, I store the credentials on the MongoConnection class; these credentials are assigned by the MongoDriver class then retrieved inside the MongoStement.cancel()
method. This could represent a security risk, as explained below.As I've noticed while developing the SSH Terminal, the JSch library implementation reveals that storing credentials inside class for some time is a security vulnerability (probably because this field could be inspected by another malicious process running on the same OS). Probably the last step above is safer considering that the ADS classes are obfuscated and thus the malicious process cannot reference these credentials.
Thank you for your input. Implemented it as suggested. There are few challenges worth mentioning here:
MongoStatement.cancel()
(to query "whatsmyuri", currentOp() and killOp() ) because it would not be executed instantly but wait until the server connection is released from the connection pool (i.e. after the long running query has finished); DB.authenticate(user, password)
on the new DB instance created at previous step. In order to perform this, I store the credentials on the MongoConnection class; these credentials are assigned by the MongoDriver class then retrieved inside the MongoStement.cancel()
method. This could represent a security risk, as explained below.As I've noticed while developing the SSH Terminal, the JSch library implementation reveals that storing credentials inside class for some time is a security vulnerability (probably because this field could be inspected by another malicious process running on the same OS). Probably the last step above is safer considering that the ADS classes are obfuscated and thus the malicious process cannot reference these credentials.
Issue #8132 |
Closed |
Fixed |
Resolved |
Completion |
No due date |
Fixed Build nosql-jdbc 0.9.1 |
No time estimate |
1 issue link |
relates to #13171
Issue #13171Revisit how to terminate queries in MongoDB in a Replica Set environment |
The only way we've found so far to cancel a long running query is to use
db.currentOp()
which lists all active (pending) operations (i.e. that are still running on the MongoDB server), then usedb.killOp(opid)
for every opid returned by the previous command.Some filters can be applied on
currentOp()
, of course (e.g. consider only the objects that have the property "op" : "query" set), but there is no guarantee that only the operation associated to the current statement / user is cancelled (killed) .Do you have any suggestions on this feature?
The DBCursor class has a close() method that sends an OP_KILL_CURSORS message, but this doesn't work for pending queries (because the iterator field,
DBCursor._it
is not yet assigned). Probably this message should be used only to release resources, not to cancel pending operations.