2013-03-01 65 views
2

假设我有一对夫妇的脚本发送(合法!)的电子邮件。每个脚本处理更大列表的一部分,并且它们同时运行。在发送之前,必须检查每个地址以避免两次发送到相同的地址。工作,避免锁

要做到这一点,我创建了一个简单的表(MySQL 5.1中,InnoDB的),只用电子邮件地址。如果它不在表格中,则添加它并发送邮件。现在我需要避免多个脚本同时测试同一个地址并错误地推断它没有被发送到的竞争条件。我想我可以使用这个锁,但我宁愿不这样做,因为性能的原因。

所以我想知道如果下面的选择是正确的:

  • 在地址栏
  • 只需插入地址加入了独特的指数,没有选择
  • 陷阱MySQL的检查返回错误代码:如果它是1062,则该地址已存在。

在此设置中,是否仍有竞争条件的可能性?我的意思是:是否仍有可能两个几乎同时插入地址的脚本都断定该邮件尚未发送?或者我应该使用锁吗?

感谢, 斯泰恩

+0

出于兴趣,为什么不使用1个脚本? – George 2013-03-01 10:32:44

+0

这些电子邮件从哪里来?如果脚本在电子邮件实际发送之前崩溃,是否是一个问题?是什么让你认为锁不能正常工作? (除此之外,唯一索引是避免欺骗的有效方法。) – 2013-03-01 10:46:09

+0

@ F4r-20:启用到后缀服务器的多个并发连接。 – svdr 2013-03-01 10:55:31

回答

0

首先我觉得数据库不是这样做的最好的地方。虽然你的更大的名单正在发送电子邮件(由于你试图瘫痪,我猜测的规模很大),但你必须使用临时表,因为你不想限制发送不同的电子邮件给以前的邮件。

缓存将是显而易见的选择,在这里维持地址列表,或服务器作为共享内存资源。

但是你能做到这一点在数据库中,并从我的理解,如果一个电子邮件地址存在不止一次因为所有你正在做的是检查一个过去没有被发送到是不是真的至关重要。如果没有锁定策略,您无法真正控制多个脚本同时发送到同一地址的争用情况。但是,您可以通过使用索引来提高效率。我不会索引实际地址,但会创建一个带有CRC32散列地址的新列(可以是只占用4个字节内存的32位无符号整数)。由于生日悖论,使用CRC32方法您还必须检查查询中的电子邮件地址。

例如:

SELECT COUNT(*) FROM email_addresses 
WHERE email_address_crc = CRC32(?address) 
AND email_address = ?address 

有一些东西,是高效应有助于避免竞态条件但正如我曾说过,以保证唯一方法是锁定数据库,而每封电子邮件被发送,所以你然后可以保留一个确切的清单 - 这不幸的是没有规模,并且意味着发送电子邮件的并行任务可能无济于事。

编辑回应下面的评论:

正如我居然忘了解决SVDR的替代锁定解决方案的评论中指出。确实,如果地址存在,那么包含电子邮件地址(或包含活动ID和地址的复合索引)的唯一索引确实会抛出MySQL异常,从而导致使用并行脚本发送到相同地址的工作解决方案同时。但是,如果在脚本尝试发送电子邮件之前输入地址,则很难处理任何异常,例如由于SMTP错误/网络问题而未发送电子邮件,这可能会导致收件人无法收到电子邮件。还提供这是一个非常简单的INSERT和SELECT,它应该很好,只是为了捕获MySQL异常,但是如果有更复杂的事情,例如事务中的包装命令或使用SELECT FOR UPDATE等,这可能导致死锁情况。

另一个需要考虑的因素是,如果使用INNODB,这个限制是767字节,因为电子邮件地址的最大有效长度是254(长度+1字节)如果使用VARCHAR),你应该没问题,因为你没有一些巨大的主键。

指数表现也应该被解决,CHAR和VCHAR应该被评估。 CHAR字段上的索引查找速度通常比等同的VCHAR查找速度快15% - 25% - 根据所使用的表引擎,固定宽度的表大小也可以提供帮助。总而言之,是的,你的非锁定解决方案是可行的,但应该根据你的确切需求仔细测试和评估(我不能评论具体细节,因为我假设你的现实生活场景比你的SO问题更复杂)。正如答案的第一行中所述,我仍然相信数据库不是最好的地方,而且缓存或共享内存空间将更加高效且易于实现。

+0

谢谢!我们需要持久性,因为广告系列可能会重新发送给添加的收件人,我们需要再次进行检查。好主意使用散列作为索引。关于我的替代锁定:你能解释为什么这不起作用吗? – svdr 2013-03-04 20:27:07

+0

@svdr我会编辑我的答案 - 我得到了另一种方法,我完全忘记了解决这个问题! – Steve 2013-03-04 20:53:56

+0

感谢您的广泛答复。我会做一些测试以找到最佳解决方案。一旦我达到了15的声望,我会尽快回复你的答案;) – svdr 2013-03-05 21:10:14