简体   繁体   English

MySQL MyISAM / InnoDB更新不是两个连接之间的原子更新(强制写入?)

[英]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. 更新:我们尝试将数据库简单地转换为InnoDB,但是我们仍然遇到相同的问题。 autocommit is on. autocommit已开启。 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. 更新2:我们通过将表设置为InnoDB 并将全局事务隔离级别设置为SERIALIZABLE来使事情正常运行,但是这明显降低了事情的速度。 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). 我在MySQL中遇到一个问题,该问题是无法立即从另一个连接(恰好是SOLR更新查询)看到从一个连接进行的写操作。

It's something like this: 就像这样:

  1. A user makes a change in the web app. 用户在Web应用程序中进行更改。
  2. We note the current revision number, r1. 我们记下当前的修订号r1。
  3. The MySQL table (MyISAM) is written with the change and next revision, r2. MySQL表(MyISAM)包含更改和下一个修订版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. 我们通过HTTP向Solr发出信号,以使用修订版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. Solr(通过不同的连接)向MySQL查询更改> r1,但未获取在步骤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. 如果这是正常行为,则必须采用某种方法强制MySQL将其连接写/刷新回磁盘以强制原子操作,并保证其他连接将看到更改。 However, again, I can't find any mention of this for MyISAM tables. 但是,同样,对于MyISAM表,我找不到任何提及。

I should also add that if I explicitly put a short delay (1-2 secs) between steps 3 and 4, things work properly. 我还应该补充一点,如果我在第3步和第4步之间明确放置了短暂的延迟(1-2秒),则一切正常。

Here are the versions of MySQL we are running: 以下是我们正在运行的MySQL版本:

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. MyISAM不会刷新到磁盘,它会写入文件系统缓冲区,并且操作系统最终会负责写入磁盘。

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. 但是无论如何,即使另一个查询,即使在另一个会话中,也应该能够立即读取MyISAM数据,即使该查询是从文件系统缓冲区中读取的也是如此。 That part should be transparent to the mysqld process. 该部分对于mysqld进程应该是透明的。

There is also no transaction isolation in MyISAM, so there's no such thing as an uncommitted change. MyISAM中也没有事务隔离,因此不存在未提交的更改。 Regardless of transaction isolation mode, any session should be able to read any completed change against a MyISAM table. 无论事务隔离模式如何,任何会话都应该能够读取针对MyISAM表的所有完成的更改。

So your described steps, with step 5 not seeing the change to r2, should never happen if you use MyISAM tables. 因此,如果您使用MyISAM表,那么您描述的步骤(第5步看不到r2的更改)将永远不会发生。 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. 无论如何,这是有争议的,因为您确实应该使用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. 您可能希望事务隔离为READ-COMMITTED ,它不会像SERIALIZABLE那样阻止并发,但是它确实允许事务查看任何数据的最新版本。 That is, if you commit a change, and Solr is using READ-COMMITTED, then Solr should see the change immediately. 也就是说,如果您提交更改,并且Solr使用的是READ-COMMITTED,那么Solr应该立即看到更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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