【问题标题】:MySQL SQL_NO_CACHE not workingMySQL SQL_NO_CACHE 不工作
【发布时间】:2012-05-10 15:18:51
【问题描述】:

我有一个表 (InnoDB),它经常被插入、更新和读取(通常间隔几毫秒)。我注意到有时在 INSERT/UPDATE 之后的 SELECT 语句会得到陈旧的数据。我认为这是由于缓存造成的,但是在将 SQL_NO_CACHE 放在它前面之后并没有真正做任何事情。

如何确保 SELECT 始终等到前一个 INSERT/UPDATE 完成而不从缓存中获取数据?请注意,这些语句是从单独的请求中执行的(不在同一代码执行中)。

也许我误解了 SQL_NO_CACHE 的实际作用......

更新

@Uday,INSERT、SELECT 和 UPDATE 语句如下所示:

INSERT myTable (id, startTime) VALUES(1234, 123456)

UPDATE myTable SET startTime = 123456 WHERE id = 1234

SELECT SQL_NO_CACHE * FROM myTable ORDER BY startTime

我尝试使用交易但没有成功。

更多更新

我认为这实际上是 INSERT 的问题,而不是 UPDATE 的问题。 SELECT 语句总是尝试获取按时间排序的最新行。但由于 INSERT 不执行任何表级锁定,因此 SELECT 可能会获取旧数据。有没有办法在执行 INSERT 时强制表级锁定?

【问题讨论】:

  • 您是否可以发布 SELECT 和 UPDATE 的示例......
  • 你在用什么isolation level?如果您使用 READ UNCOMMITTED 或“脏读”,则可能会发生这种情况。
  • @MarcusAdams 无论 InnoDB 的默认隔离级别是什么,都不确定这是否能回答您的问题。
  • @pixelfreak 查看我的答案,以不同的方式执行此操作......

标签: mysql node.js innodb


【解决方案1】:

查询缓存不是问题。写入使缓存无效。

MySQL 优先考虑写入,并且使用默认隔离级别 (REPEATABLE READ),您的 SELECT 必须等待 UPDATE 完成。

如果您为 MyISAM 启用了CONCURRENT INSERTS,则可以区别对待 INSERT,而且 InnoDB 使用记录锁定,因此它不必等待表末尾的插入。

那么这可能是一种竞争条件吗?您确定您的 SELECT 发生在 UPDATE 之后吗?您是否正在从可能尚未传播更新的复制服务器读取数据?

如果问题在于并发 INSERT,您需要在 MyISAM 上禁用 CONCURRENT INSERT,或者在 INSERT 期间使用 LOCK TABLES 显式锁定表。 InnoDB 的解决方案是相同的,使用 LOCK TABLES 显式锁定 INSERT 上的表。

【讨论】:

  • @pixelfreak,我刚刚更新了关于 INSERT 的答案。您要么需要使用 MyISAM 关闭该功能,要么使用 LOCK TABLES 显式锁定表。
  • Marcus,我使用的是 InnoDB,而不是 MyISAM
  • @pixelfreak,InnoDB 使用记录锁定,因此 SELECT 不会被表末尾的插入阻塞。解决方法是一样的。插入时使用 LOCK TABLES 显式锁定表。对不起,我也在更新我的答案,虽然你说你的更新是问题,而不是插入。 :)
【解决方案2】:

A)
如果您根本不需要缓存(对于任何 SELECT),请禁用查询 完全缓存。

B)
如果你只想要一个会话,你可以这样做 “设置会话查询缓存类型=0;”这将为此设置 特定的会话。

在任何一种情况下都额外使用 SQL_NO_CAHCE。

【讨论】:

  • 1) 再添加一列,例如“更新”,默认为 0 2) 在更新时将其设为 1。在 SELECT 中另外使用“WHERE update = 1”条件。
猜你喜欢
  • 2020-02-23
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-06-10
  • 2014-10-23
相关资源
最近更新 更多