2016-06-08 59 views
0

我有一个Rails web应用程序依赖于mysql数据库。从mysqldump文件重新加载mysql数据库,并确保读取请求的完整性

有一个脚本运行mysqldump另一个数据库并重新加载上面的数据库。

的命令是这样的:

mysqldump -uuser1 -ppassword1 --opt db1 > dumpfile 

mysql -uuser2 -ppassword2 db2 < dumpfile 

转储文件非常小(< 15MB)。从转储文件重新加载数据库不到150ms。

转储文件包含了一系列的部分象下面这样:

-- 
-- Table structure for table `some_table` 
-- 

DROP TABLE IF EXISTS `some_table`; 
/*!40101 SET @saved_cs_client  = @@character_set_client */; 
/*!40101 SET character_set_client = utf8 */; 
CREATE TABLE `some_table` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    ... 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; 
/*!40101 SET character_set_client = @saved_cs_client */; 

-- 
-- Dumping data for table `some_table` 
-- 

LOCK TABLES `some_table` WRITE; 
/*!40000 ALTER TABLE `some_table` DISABLE KEYS */; 
INSERT INTO `some_table` VALUES (1,...); 
/*!40000 ALTER TABLE `some_table` ENABLE KEYS */; 
UNLOCK TABLES; 

Rails应用程序运行时发生这种情况。 (让我们假设在重新加载数据库之前关闭Rails应用程序是而不是的一个选项。)

在重新加载数据库时可能会出现用户Web请求。如果是这样,数据库读取请求的完整性将受到影响(例如,表是空的),所以用户会得到错误或异常。你如何避免这种情况?

有没有办法确保数据库重新加载时不会发生错误的读取?如使用事务,锁定整个数据库,以便读取请求等待,直到数据库重新加载完成?我将如何生成这样的“读安全”转储文件(我应该考虑mysqldump的任何选项)?

谢谢。

+0

我想这取决于你的配置,但我会告诉你我们在哪里工作。首先我会说从转储中加载你的数据库在很大程度上被认为是不好的做法。我们有一个负载平衡器,所以我们基本上只是将所有流量都导向一个实例,而我们在另一个实例上导入转储。然后,我们将所有流量导向更新的实例,同时更新第二个实例。一旦两者都被更新,我们就分割两个实例之间的流量。 –

+0

感谢您的评论。在这种情况下,数据库非常小。所以我只需要防范一个非常小的时间窗口。此外,此操作是应用程序的一部分,不属于部署过程。所以编辑可以随时触发这个事件。您是手动更改负载均衡器还是通过脚本更改? –

+0

我们通过脚本改变它。您是否证实在更新期间尝试访问数据库会导致问题?就我个人而言,我认为这个问题的正确答案是不允许用户从UI触发转储,但可能有一些方法可以正确执行,我不知道。 –

回答

0

作为加载转储文件的一部分而开始的任何事务将由create table语句隐含地提交(这对于MySQL中的大多数DDL语句都是如此)。

它看起来好像调用FLUSH TABLES WITH READ LOCK获取全局锁,这可能是您需要的。