Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are some mysql connections selecting old data the mysql database after a delete + insert?

I'm having a problem with the sessions in my python/wsgi web app. There is a different, persistent mysqldb connection for each thread in each of 2 wsgi daemon processes. Sometimes, after deleting old sessions and creating a new one, some connections still fetch the old sessions in a select, which means they fail to validate the session and ask for login again.

Details: Sessions are stored in an InnoDB table in a local mysql database. After authentication (through CAS), I delete any previous sessions for that user, create a new session (insert a row), commit the transaction, and redirect to the originally requested page with the new session id in the cookie. For each request, a session id in the cookie is checked against the sessions in the database.

Sometimes, a newly created session is not found in the database after the redirect. Instead, the old session for that user is still there. (I checked this by selecting and logging all of the sessions at the beginning of each request). Somehow, I'm getting cached results. I tried selecting the sessions with SQL_NO_CACHE, but it made no difference.

Why am I getting cached results? Where else could the caching occur, and how can stop it or refresh the cache? Basically, why do the other connections fail to see the newly inserted data?

like image 376
jmilloy Avatar asked Feb 16 '12 20:02

jmilloy


2 Answers

MySQL defaults to the isolation level "REPEATABLE READ" which means you will not see any changes in your transaction that were done after the transaction started - even if those (other) changes were committed.

If you issue a COMMIT or ROLLBACK in those sessions, you should see the changed data (because that will end the transaction that is "in progress").

The other option is to change the isolation level for those sessions to "READ COMMITTED". Maybe there is an option to change the default level as well, but you would need to check the manual for that.

like image 99
a_horse_with_no_name Avatar answered Sep 20 '22 19:09

a_horse_with_no_name


Yes, it looks like the assumption is that you are only going to perform a single transaction and then disconnect. If you have a different need, then you need to work around this assumption. As mentioned by @a_horse_with_no_name, you can put in a commit (though I would use a rollback if you are not actually changing data). Or you can change the isolation level on the cursor - from this discussion I used this:

dbcursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")

Or, it looks like you can set auto commit to true on the connection:

dbconn.autocommit(True)

Though, again, this is not recommended if actually making changes in the connection.

like image 28
Rob Lusardi Avatar answered Sep 19 '22 19:09

Rob Lusardi