简体   繁体   中英

MySQL MyISAM/InnoDB updates are not atomic across two connections (force write?)

Update: We tried simply converting the database to InnoDB, but we are still experiencing the same problem. autocommit is on. Is there perhaps some additional statement that is needed to make sure the change can be seen by another connection?

Update 2: We managed to get things working by setting the tables to InnoDB and setting the global transaction isolation level to SERIALIZABLE , however that noticeably slows things down. Also, not all of us are fully convinced this has solved the issue, as the slowdown may simply have given the race condition enough time to execute in the proper order. At any rate we are continuing to investigate.


I am experiencing an issue in MySQL where a write made from one connection is not being seen immediately from another connection (which happens to be a SOLR update query).

It's something like this:

  1. A user makes a change in the web app.
  2. We note the current revision number, r1.
  3. The MySQL table (MyISAM) is written with the change and next revision, r2. [At this point in the code the change should have been written to the database, and if we query it again from the same connection we will see it.]
  4. We signal Solr over http to update itself with revision r1.
  5. Solr (from a different connection) queries MySQL for changes > r1, but is not picking up up the change that was just written in step 3.

Is this expected/normal behavior? I can't find anything in the documentation that suggests updates are not atomic across connections. Bear in mind that at the point the second connection is signalled to update itself, the change should have already been written to the database.

If this is normal behavior, there must be some way to force MySQL to write/flush its connection back to disk to force normal atomic operation and guarantee other connections will see the change. However, again, I can't find any mention of this for MyISAM tables.

I should also add that if I explicitly put a short delay (1-2 secs) between steps 3 and 4, things work properly.

Here are the versions of MySQL we are running:

mysql-server-5.1.66-2.el6_3.x86_64
php-mysql-5.3.3-14.el6_3.x86_64
mysql-libs-5.1.66-2.el6_3.x86_64
mysql-5.1.66-2.el6_3.x86_64

MyISAM does not flush to disk, it writes to the filesystem buffer and the OS takes care of writing to disk eventually.

But regardless, another query, even one in another session, should be able to read that MyISAM data immediately, even if it reads it out of the filesystem buffer. That part should be transparent to the mysqld process.

There is also no transaction isolation in MyISAM, so there's no such thing as an uncommitted change. Regardless of transaction isolation mode, any session should be able to read any completed change against a MyISAM table.

So your described steps, with step 5 not seeing the change to r2, should never happen if you use MyISAM tables. I would therefore guess that you misinterpreted the sequence of actions, and you were actually trying to read changes that hadn't actually been made yet.

Anyway, it's moot because you really should be using InnoDB. Then transaction isolation does matter. You probably want transaction isolation of READ-COMMITTED , which won't block concurrency like SERIALIZABLE does, but it does allow a transaction to see the most recent version of any data. That is, if you commit a change, and Solr is using READ-COMMITTED, then Solr should see the change immediately.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM