更新表时防止读取

时间:2010-03-07 10:31:44

标签: mysql database

在MySQL中:

我每隔一分钟清空一次表并用新数据填充它。现在我希望用户不应该在填充过程中,在确定之前或之后读取数据。

我如何实现这一目标? 是交易方式吗?

3 个答案:

答案 0 :(得分:3)

假设您使用交易引擎(通常为Innodb),请在同一交易中清除并重新填充表格。

确保您的读者使用READ_COMMITTED或更高的事务隔离级别(默认值为REPEATABLE READ更高)。

这样,读者可以在更新期间继续阅读表格的旧内容。

有几点需要注意:

  • 如果表格太大以至于耗尽了回滚区域 - 如果更新整个(例如)1M行表,则可以这样做。当然这是可调的但有限制
  • 如果事务部分失败并被回滚 - 在InnoDB中回滚大事务是非常低效的(它针对提交进行了优化,而不是回滚)
  • 小心死锁并锁定等待超时,如果您使用大型交易,则更有可能。

答案 1 :(得分:2)

您可以在操作期间LOCK使用您的牌桌:

http://dev.mysql.com/doc/refman/5.1/en/lock-tables.html

  

表锁仅保护   其他不恰当的读写   会话。会议持有   锁,甚至读锁,都可以执行   表级操作,如DROP   表。截断操作不是   事务安全,因此发生错误   如果会话在一个期间尝试一个   积极交易或持有   桌锁。

我对MySql的内部行版本控制机制(或者实际上,如果有的话)知之甚少,但其他数据库(Oracle,Postgresql,以及最近的Sql Server)已投入大量精力允许编写者阻止读者,只要读者可以访问在更新/写入过程开始之前存在的行的版本。提交更新后,该行的版本将变为可供所有读者使用的版本,从而避免了MySql中的上述行为将引入的瓶颈。

  

此策略可确保表锁定   是无死锁的。但是,有   您需要注意的其他事项   关于这个政策:如果你正在使用   LOW_PRIORITY WRITE锁定表,   它只意味着MySQL等待   这个特殊的锁直到有   没有其他想要READ的会话   锁。当会话得到了   WRITE锁定正在等待获取   锁定锁中的下一个表   表列表,所有其他会话等待   用于释放WRITE锁。如果   这成为一个严重的问题   你应该考虑你的申请   将一些表转换为   交易安全表。

答案 2 :(得分:0)

您可以根据需要将数据加载到影子表中,然后立即将影子和实际交换到RENAME TABLE:

truncate table shadow;     # make sure it is clean to start with
insert into shadow .....;  # lots of inserts etc against shadow table
rename table active to temp, shadow to active, temp to shadow;
truncate table shadow;     # throw away the old active data

重命名语句是原子的。中间名称“temp”用于帮助交换temp和active的名称。

这适用于所有存储引擎。

Rename table - MySQL Manual