Discussion:
"The connection may have been used since this write, cannot obtain a result"
(too old to reply)
Leif Mortenson
2011-07-22 02:19:01 UTC
Permalink
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.

---
jvm 1 | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1 | at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1 | at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---

Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?

Cheers,
Leif
Nat
2011-07-22 02:25:17 UTC
Permalink
What's writeconcern you passed into update function()?
-----Original Message-----
From: Leif Mortenson <leif.mortenson-***@public.gmane.org>
Sender: mongodb-user-/***@public.gmane.org
Date: Fri, 22 Jul 2011 11:19:01
To: <mongodb-user-/***@public.gmane.org>
Reply-To: mongodb-user-/***@public.gmane.org
Subject: [mongodb-user] "The connection may have been used since this write,
cannot obtain a result"

Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.

---
jvm 1 | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1 | at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1 | at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---

Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?

Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Scott Hernandez
2011-07-22 03:30:25 UTC
Permalink
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.

If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.

I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.

On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Leif Mortenson
2011-07-22 03:46:27 UTC
Permalink
Scott, Nat,
Thank you for your quick response as always.

This particular call had a WriteConcern.NONE. I understand that in
this case, the getLastError would not do anything. But this code was
shared and is called with different WriteConcern values.

We are are currently using the 2.6.3 Java driver.

We can go through and change our code so getLastError is never called
when WriteConcern was NONE. But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably. In this
case, this system has already gone into production after going through
extensive testing without any problems. Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal? Alternatively, it should always throw an
IllegalStateException. The second would probably cause problems for
existing users if they are doing what we were.

Thanks again,
Cheers,
Leif

On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Scott Hernandez
2011-07-22 03:50:19 UTC
Permalink
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.

On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Leif Mortenson
2011-07-22 04:23:25 UTC
Permalink
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error. I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up. If this failed 100% of the time I would have no problem
with it. But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.

We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.

Cheers,
Leif

On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Scott Hernandez
2011-07-22 04:33:16 UTC
Permalink
You can use the getCachedLastError method which will not call the
server, ever. That is probably what you want to use in your
abstraction layer.
http://api.mongodb.org/java/current/com/mongodb/WriteResult.html#getCachedLastError()

As I said, this will only happen if the connection used on the update
has been used between that call and your next call. It means that you
have contention for you connections such that the thread didn't get it
back before some other thread used it (thread have affinity for the
same connection).

On Fri, Jul 22, 2011 at 12:23 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error.   I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up.   If this failed 100% of the time I would have no problem
with it.  But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.
We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Leif Mortenson
2011-07-22 05:00:14 UTC
Permalink
Scott,
Thank you. We will look at the other method.

I am concerned about this issue because of the very fact that its
behavior depends on whether or not other threads are active on the
system. That is inherently dangerous because simple test cases will
work perfectly while a larger live system will be much more likely to
encounter the problem.

We can work around this on our end now that it is understood. I don't
want to push endlessly other than to voice my concern that the current
API design is dangerous in the way I described. If it is possible to
fix without affecting performance then I think it would be a valuable
change to help improve the overall reliability of the software. As I
said, we did not discover this problem until our system had been live
for a couple weeks.

Cheers,
Leif

On Fri, Jul 22, 2011 at 1:33 PM, Scott Hernandez
Post by Scott Hernandez
You can use the getCachedLastError method which will not call the
server, ever. That is probably what you want to use in your
abstraction layer.
http://api.mongodb.org/java/current/com/mongodb/WriteResult.html#getCachedLastError()
As I said, this will only happen if the connection used on the update
has been used between that call and your next call. It means that you
have contention for you connections such that the thread didn't get it
back before some other thread used it (thread have affinity for the
same connection).
On Fri, Jul 22, 2011 at 12:23 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error.   I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up.   If this failed 100% of the time I would have no problem
with it.  But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.
We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Scott Hernandez
2011-07-22 05:41:52 UTC
Permalink
In the documentation for the (java) driver it states if you need to do
operations on the same connection, like you are doing, then you must
do:

db.RequestStart()
... // ops
db.RequestEnt()

http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency Also, the
documentation for the DB class, and the method, also mention this.

It is important to understand how the driver works in order to design
your application and achieve the behavior you require.

I can understand that you this is a learning process and that some of
you assumptions, and tests, turned out to be different under load and
in production. I would suggest that you take this opportunity to
design more strenuous and concurrent tests. I'm sure this idea comes
as no surprise but I have found that doing this from the beginning
helps keep these kinds of surprises from coming up later in the game,
as they say.

Please let us know if there are any specific places where the
documentation could be updated, or changed, to make this more clear.

On Fri, Jul 22, 2011 at 1:00 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Thank you.  We will look at the other method.
I am concerned about this issue because of the very fact that its
behavior depends on whether or not other threads are active on the
system.   That is inherently dangerous because simple test cases will
work perfectly while a larger live system will be much more likely to
encounter the problem.
We can work around this on our end now that it is understood.  I don't
want to push endlessly other than to voice my concern that the current
API design is dangerous in the way I described.  If it is possible to
fix without affecting performance then I think it would be a valuable
change to help improve the overall reliability of the software.   As I
said, we did not discover this problem until our system had been live
for a couple weeks.
Cheers,
Leif
On Fri, Jul 22, 2011 at 1:33 PM, Scott Hernandez
Post by Scott Hernandez
You can use the getCachedLastError method which will not call the
server, ever. That is probably what you want to use in your
abstraction layer.
http://api.mongodb.org/java/current/com/mongodb/WriteResult.html#getCachedLastError()
As I said, this will only happen if the connection used on the update
has been used between that call and your next call. It means that you
have contention for you connections such that the thread didn't get it
back before some other thread used it (thread have affinity for the
same connection).
On Fri, Jul 22, 2011 at 12:23 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error.   I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up.   If this failed 100% of the time I would have no problem
with it.  But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.
We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Leif Mortenson
2011-07-25 04:40:09 UTC
Permalink
Scott,
Thank you for the followup. I had not known about the concurrency
methods. Should our code always use that when calling
getLastError()? Or is the getCachedLastError() method a helper to
work around this issue that we should always be using? In what cases
would you want to use getLastError rather than getCachedLastError?
It sounds dangerous unless concurrency is being used.

I don't think we are doing anything else where concurrency is going to
be an issue

Thanks again for all your prompt help.

Cheers,
Leif

On Fri, Jul 22, 2011 at 2:41 PM, Scott Hernandez
Post by Scott Hernandez
In the documentation for the (java) driver it states if you need to do
operations on the same connection, like you are doing, then you must
db.RequestStart()
... // ops
db.RequestEnt()
http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency Also, the
documentation for the DB class, and the method, also mention this.
It is important to understand how the driver works in order to design
your application and achieve the behavior you require.
I can understand that you this is a learning process and that some of
you assumptions, and tests, turned out to be different under load and
in production. I would suggest that you take this opportunity to
design more strenuous and concurrent tests. I'm sure this idea comes
as no surprise but I have found that doing this from the beginning
helps keep these kinds of surprises from coming up later in the game,
as they say.
Please let us know if there are any specific places where the
documentation could be updated, or changed, to make this more clear.
On Fri, Jul 22, 2011 at 1:00 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Thank you.  We will look at the other method.
I am concerned about this issue because of the very fact that its
behavior depends on whether or not other threads are active on the
system.   That is inherently dangerous because simple test cases will
work perfectly while a larger live system will be much more likely to
encounter the problem.
We can work around this on our end now that it is understood.  I don't
want to push endlessly other than to voice my concern that the current
API design is dangerous in the way I described.  If it is possible to
fix without affecting performance then I think it would be a valuable
change to help improve the overall reliability of the software.   As I
said, we did not discover this problem until our system had been live
for a couple weeks.
Cheers,
Leif
On Fri, Jul 22, 2011 at 1:33 PM, Scott Hernandez
Post by Scott Hernandez
You can use the getCachedLastError method which will not call the
server, ever. That is probably what you want to use in your
abstraction layer.
http://api.mongodb.org/java/current/com/mongodb/WriteResult.html#getCachedLastError()
As I said, this will only happen if the connection used on the update
has been used between that call and your next call. It means that you
have contention for you connections such that the thread didn't get it
back before some other thread used it (thread have affinity for the
same connection).
On Fri, Jul 22, 2011 at 12:23 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error.   I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up.   If this failed 100% of the time I would have no problem
with it.  But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.
We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Scott Hernandez
2011-07-25 13:58:44 UTC
Permalink
As I said in my first response to this thread, you should really not
be calling getLastError yourself but should be using the
WriteConcern.Safe in your write methods or set at the
collection/db/mongo level. If you do need to see the results of that
getLastError response then using the cache version will mean you don't
need to contact the server, ever. The difference between the two is
wether a call to the server will be made (and if you can change the
WriteConcern options).

Concurrency isn't something you use or don't use. It is inherent in
your application (runtime) at all times. It is good to be aware of it
since it can be an issue for the most simple of programs or functions.

On Mon, Jul 25, 2011 at 12:40 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Thank you for the followup.  I had not known about the concurrency
methods.   Should our code always use that when calling
getLastError()?  Or is the getCachedLastError() method a helper to
work around this issue that we should always be using?  In what cases
would you want to use getLastError rather than getCachedLastError?
It sounds dangerous unless concurrency is being used.
I don't think we are doing anything else where concurrency is going to
be an issue
Thanks again for all your prompt help.
Cheers,
Leif
On Fri, Jul 22, 2011 at 2:41 PM, Scott Hernandez
Post by Scott Hernandez
In the documentation for the (java) driver it states if you need to do
operations on the same connection, like you are doing, then you must
db.RequestStart()
... // ops
db.RequestEnt()
http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency Also, the
documentation for the DB class, and the method, also mention this.
It is important to understand how the driver works in order to design
your application and achieve the behavior you require.
I can understand that you this is a learning process and that some of
you assumptions, and tests, turned out to be different under load and
in production. I would suggest that you take this opportunity to
design more strenuous and concurrent tests. I'm sure this idea comes
as no surprise but I have found that doing this from the beginning
helps keep these kinds of surprises from coming up later in the game,
as they say.
Please let us know if there are any specific places where the
documentation could be updated, or changed, to make this more clear.
On Fri, Jul 22, 2011 at 1:00 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Thank you.  We will look at the other method.
I am concerned about this issue because of the very fact that its
behavior depends on whether or not other threads are active on the
system.   That is inherently dangerous because simple test cases will
work perfectly while a larger live system will be much more likely to
encounter the problem.
We can work around this on our end now that it is understood.  I don't
want to push endlessly other than to voice my concern that the current
API design is dangerous in the way I described.  If it is possible to
fix without affecting performance then I think it would be a valuable
change to help improve the overall reliability of the software.   As I
said, we did not discover this problem until our system had been live
for a couple weeks.
Cheers,
Leif
On Fri, Jul 22, 2011 at 1:33 PM, Scott Hernandez
Post by Scott Hernandez
You can use the getCachedLastError method which will not call the
server, ever. That is probably what you want to use in your
abstraction layer.
http://api.mongodb.org/java/current/com/mongodb/WriteResult.html#getCachedLastError()
As I said, this will only happen if the connection used on the update
has been used between that call and your next call. It means that you
have contention for you connections such that the thread didn't get it
back before some other thread used it (thread have affinity for the
same connection).
On Fri, Jul 22, 2011 at 12:23 AM, Leif Mortenson
Post by Leif Mortenson
Scott,
Because the WriteResult is returned by the call which was provided the
WriteConcern, it should be possible to include a flag in the
WriteResult so it knows now to look for the last error.   I understand
completely that this was caused by by my misuse of the API, however
this was only because of some very innocent common libraries that we
had set up.   If this failed 100% of the time I would have no problem
with it.  But in reality we have made the call several 10s of millions
of times and this is the first time we got such a failure.
We have fixed this in our code for now, but I will have to make sure
that all of our developers know about this issue.
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:50 PM, Scott Hernandez
Post by Scott Hernandez
If you call getLastError() that is an intentional operation you are
taking. The WriteConcern from the update is unrelated to this call,
and that is intentional. We can update the javadocs so this is more
clear of course.
On Thu, Jul 21, 2011 at 11:46 PM, Leif Mortenson
Post by Leif Mortenson
Scott, Nat,
Thank you for your quick response as always.
This particular call had a WriteConcern.NONE.  I understand that in
this case, the getLastError would not do anything.  But this code was
shared and is called with different WriteConcern values.
We are are currently using the 2.6.3 Java driver.
We can go through and change our code so getLastError is never called
when WriteConcern was NONE.  But I view this as a dangerous bug in the
API as it is not documented and does not happen reliably.  In this
case, this system has already gone into production after going through
extensive testing without any problems.   Would it be possible for you
modify the driver so getLastError does not try to access the
connection if the WriteConcern had a value which makes its use
illegal?  Alternatively, it should always throw an
IllegalStateException.  The second would probably cause problems for
existing users if they are doing what we were.
Thanks again,
Cheers,
Leif
On Fri, Jul 22, 2011 at 12:30 PM, Scott Hernandez
Post by Scott Hernandez
This is because of the way connection pooling works with threads. It
is a result of the fact that you have high contention for the
connection pool, from other threads. You may want to increase your
connection pool size (connectionsPerHost) in MongoOptions when
creating you Mongo instance.
If you plan to call getLastError after an update then you should
simply use WriteConcern.Safe in the write/update, and you will not
have this error.
I believe there was also a bug in an old version of the driver related
to this so you should probably upgrade to the latest if you aren't
using it.
On Thu, Jul 21, 2011 at 10:19 PM, Leif Mortenson
Post by Leif Mortenson
Hi,
I got the following error from the Java driver when claling
WriteResult.getLastError immediately after doing an update.
---
jvm 1    | java.lang.IllegalStateException: The connection may have
been used since this write, cannot obtain a result
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
jvm 1    |      at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
---
Googling on this seems to show that the same connection was reused by
another thread before I could get the last error?
What needs to be done to avoid such errors?
Cheers,
Leif
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to mongodb-user+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.
Michael Häusler
2012-06-11 11:51:46 UTC
Permalink
Hi,
Post by Scott Hernandez
As I said in my first response to this thread, you should really not
be calling getLastError yourself but should be using the
WriteConcern.Safe in your write methods or set at the
collection/db/mongo level.
is there a best practice to reliably get the number of affected rows
(WriteResult.getN())? Even if you use WriteConcern.SAFE the following code
might fail with the same IllegalStateException, because getN() calls
getLastError internally:

collection.update(q, op, false, true, WriteConcern.SAFE).getN();

This occasionally produces the following stacktrace with the Java driver
version 2.7.2:

Caused by: java.lang.IllegalStateException: The connection may have been
used since this write, cannot obtain a result
at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
at com.mongodb.WriteResult.getN(WriteResult.java:127)
[...]


Best regards
Michael
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/***@public.gmane.org
To unsubscribe from this group, send email to
mongodb-user+unsubscribe-/***@public.gmane.org
See also the IRC channel -- freenode.net#mongodb
Scott Hernandez
2012-06-11 13:29:50 UTC
Permalink
You should not be getting that exception if you use WriteConcern.SAFE
as the driver holds onto the connection/socket for the write +
getLastError call which your user can't easily do.

If you can reproduce it and provide a full-stack-trace then please
file an issue in the java driver (http://jira.mongodb.org/).

If you are sharded and using mongos there was a bug where the n field,
really the whole response, was wrong after a chunk move.
Post by Michael Häusler
Hi,
Post by Scott Hernandez
As I said in my first response to this thread, you should really not
be calling getLastError yourself but should be using the
WriteConcern.Safe in your write methods or set at the
collection/db/mongo level.
is there a best practice to reliably get the number of affected rows
(WriteResult.getN())? Even if you use WriteConcern.SAFE the following code
might fail with the same IllegalStateException, because getN() calls
collection.update(q, op, false, true, WriteConcern.SAFE).getN();
This occasionally produces the following stacktrace with the Java driver
Caused by: java.lang.IllegalStateException: The connection may have been
used since this write, cannot obtain a result
        at com.mongodb.WriteResult.getLastError(WriteResult.java:98)
        at com.mongodb.WriteResult.getLastError(WriteResult.java:72)
        at com.mongodb.WriteResult.getN(WriteResult.java:127)
[...]
Best regards
Michael
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To unsubscribe from this group, send email to
See also the IRC channel -- freenode.net#mongodb
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/***@public.gmane.org
To unsubscribe from this group, send email to
mongodb-user+unsubscribe-/***@public.gmane.org
See also the IRC channel -- freenode.net#mongodb
Michael Häusler
2012-06-12 13:23:32 UTC
Permalink
Hi Scott,

thanks a lot. Updating our sharded database did indeed solve the getN-issue.

Best regards

Continue reading on narkive:
Loading...