防止MySQL中的查询缓存

时间:2013-06-10 13:45:35

标签: mysql tomcat caching connection-pooling

我正在通过JNDI资源使用tomcat连接池。

context.xml

<Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
          username="myusr" password="mypwd" driverClassName="com.mysql.jdbc.Driver"
          maxActive="1000" maxIdle="100" maxWait="10000"
          url="jdbc:mysql://localhost:3306/mydatabase" 
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" />

web.xml

<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/mydb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

数据库是MySQL数据库。

当我选择一些信息时,例如产品列表,在产品插入或删除后也会显示相同的列表。

如何防止这种情况?在这种情况下,我会看到更新的列表。

修改

query_cache_size为0且query_cache_type为ON。

那么,问题可能出在哪里?为什么要进行查询缓存?

修改

我读到了“RESET QUERY CACHE”和“FLUSH TABLES”。

他们之间有什么区别?

通过使用其中一个,拍卖/电子商务场景可能会出现问题吗?

3 个答案:

答案 0 :(得分:5)

正如Consistent Nonlocking Reads所述:

  

如果事务isolation levelREPEATABLE READ(默认级别),则同一事务中的所有一致性读取将读取该事务中第一次此类读取所建立的快照。您可以通过提交当前事务并在发出新查询之后为查询获取更新的快照。

[ deletia ]
     

如果您想查看数据库的“最新鲜”状态,请使用READ COMMITTED隔离级别或locking read

SELECT * FROM t LOCK IN SHARE MODE;

您可以在Tomcat via its Resource@defaultTransactionIsolation attribute中设置默认事务隔离级别。

答案 1 :(得分:1)

连接池与数据缓存没有任何关系(除非您专门配置它)。最佳做法是使用连接池进行数据库访问以防止失控连接(例如,使用过多的同时连接来访问数据库)并重用已打开过一次的连接(通常建立连接非常昂贵,因此可以再次使用它们) 。您还希望缓存语句本身(如PreparedStatement),因为数据库的下一个昂贵操作是确定执行计划。 (这与实际结果缓存无关)

您是否分析过您的缓存数据是否实际来自mysql,或者您是否在应用程序级别进行缓存?

另外,请确保insert&amp; update事务实际上已提交,否则显然不会有任何更改,数据看起来像是缓存的。

答案 2 :(得分:1)

RESET QUERY CACHE仅清除查询缓存。

FLUSH TABLES关闭所有表(刷新任何未写入的数据后), 清除查询缓存。

清除缓存不会导致您遇到的问题。它只是强制后续查询实际从表中获取数据(直到再次缓存这些结果)。

请注意,保证查询缓存永远不会显示过时的数据。对缓存中的查询引用的任何表的任何已提交写入都会从缓存中删除此类查询。如果您看到过时的数据,那么必须采用另一种外部机制。例如,许多ORM在某个阶段执行某些行缓存,并且这种机制可能会被破坏,或者如果没有完全按预期使用,可能会产生意外结果。

无论如何,如果query_cache_size = 0query_cache_type = OFF(或0),则会禁用查询缓存。