我想确保电子邮件只发送一次,所以我在 Oracle SQL 中使用以下语句:
update mytable set mail_sent = 't' where id = ? and mail_sent = 'f'
并检查修改的行数。如果没有行被修改,那么另一个进程首先做同样的事情并发送邮件。如果修改了 1 行,我发送邮件。(当然,如果发送邮件失败,我会重置 mail_sent。进程崩溃并将 mail_sent 留在“t”的可能性很小,因此不会发送任何邮件。我会忍受的。)
我不能完全说服自己这对于竞争条件是安全的(在进程 1 写入“t”之前进程 1 读取“f”并且进程 2 读取“f”,因此两个进程都认为他们修改了该行并发送了 2 封电子邮件。我将隔离级别设置为 SERIALIZABLE 以避免该问题,但这实际上是必要的,还是没有它我是否安全?