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

标签 php mysql solr myisam

更新:我们尝试简单地将数据库转换为 InnoDB,但我们仍然遇到同样的问题。 autocommit 开启。是否可能需要一些额外的声明来确保更改可以被另一个连接看到?

更新 2:我们设法通过将表设置为 InnoDB 并将全局事务隔离级别设置为 SERIALIZABLE 来让事情正常进行,但是这明显减慢了速度。此外,并非所有人都完全相信这已经解决了问题,因为减速可能只是让竞争条件有足够的时间以正确的顺序执行。无论如何,我们正在继续调查。


我在 MySQL 中遇到一个问题,即从一个连接进行的写入不会立即从另一个连接(恰好是 SOLR 更新查询)中看到。

是这样的:

  1. 用户在网络应用程序中进行更改。
  2. 我们注意到当前的修订号 r1。
  3. MySQL 表 (MyISAM) 是用更改和下一个 修订版 r2 编写的。 [此时代码中的更改应该已写入数据库,如果我们从同一连接再次查询它,我们将看到它。]
  4. 我们通过 http 通知 Solr 使用版本 r1 更新自身。
  5. Solr(来自不同的连接)查询 MySQL 的更改 > r1,但没有获取刚刚在步骤 3 中写入的更改。

这是预期的/正常的行为吗?我在文档中找不到任何表明更新在连接之间不是原子的。请记住,在第二个连接发出更新自身的信号时,更改应该已经写入数据库。

如果这是正常行为,则必须有某种方法强制 MySQL 将其连接写入/刷新回磁盘以强制执行正常的原子操作并保证其他连接将看到更改。但是,同样,我找不到关于 MyISAM 表的任何提及。

我还应该补充一点,如果我在第 3 步和第 4 步之间明确设置一个短暂的延迟(1-2 秒),一切都会正常进行。

以下是我们正在运行的 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 不刷新到磁盘,它写入文件系统缓冲区,操作系统负责最终写入磁盘。

但是无论如何,另一个查询,即使是另一个 session 中的查询,也应该能够立即读取该 MyISAM 数据,即使它是从文件系统缓冲区中读取的。该部分对 mysqld 进程应该是透明的。

MyISAM 中也没有事务隔离,因此不存在未提交的更改。无论事务隔离模式如何,任何 session 都应该能够读取针对 MyISAM 表的任何已完成更改。

因此,如果您使用 MyISAM 表,那么您所描述的步骤(第 5 步没有看到对 r2 的更改)应该永远不会发生。因此,我猜测您误解了操作的顺序,而您实际上是在尝试读取尚未实际进行的更改。

无论如何,这没有实际意义,因为您确实应该使用 InnoDB。那么事务隔离就很重要了。您可能需要 READ-COMMITTED 的事务隔离,这不会像 SERIALIZABLE 那样阻止并发,但它确实允许事务查看任何数据的最新版本。也就是说,如果您提交更改,并且 Solr 正在使用 READ-COMMITTED,那么 Solr 应该立即看到更改。

关于php - MySQL MyISAM/InnoDB 更新不是跨两个连接的原子更新(强制写入?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18902804/

相关文章:

php - 使用编辑按钮将mysql数据放入html表中

php - 简单的 Ajax 过滤器不返回结果

php - 如何使用链接和使用 PHP、MySQL 获取来按字母顺序对表中的列进行排序?

solr排序,我想首先指定一个特定的文档

php - 流明访问 Controller 外部的请求对象

php - CodeIgniter - 引用 URL - 保存在数据库中

php - MYSQL返回重复行

php - 为什么我的 php 脚本不能连接到 mysql?

java - Solr - 索引大型数据库

elasticsearch - 如何在ElasticSearch或SOLR中为共享文件夹建模?