2012-03-27 41 views
1

我有这个表:使用MySQL具有良好的原子唯一索引不提高错误

User 
    id INT PK 
    login VARCHAR UNIQUE 

我想知道的最佳方式来处理UNIQUE索引插入(例如:新用户创建)

1)我可以简单地插入,当一个“重复的条目提出了”我捕获异常并处理它在应用

=>我不知道这是最好的解决方案,这样做

2)I可以SELECT ... WHERE登录= ...然后插入时没有找到记录,或者如果选择发现一些

=>这不是原子,插入件可以选择之间发生,INSERT

显示错误

3)我就可以开始交易,SELECT FOR UPDATE,INSERT然后提交时,没有发现任何记录或ROLLBACK,如果用户已经存在

=>这是行不通的,因为MySQL不显示错误锁定没有现有的线...所以它肯定会导致死锁

那么处理这个问题的最佳方法是什么简单的研究案例?

回答

0

你可以做一个

INSERT IGNORE ... 

MySQL manual INSERT

或者

REPLACE ... 

MySQL manual REPLACE

你也可以接受一些问题的答案。这将鼓励更多的人来帮助你。

+0

我想我也可以使用ON DUPLICATE KEY,但是我真的很好奇,是否有解决方案来查找现有密钥而不是尝试插入并查看正在发生的事情。 – nemenems 2012-03-27 15:43:09

+0

@nemenems你为什么要这么做?这只是您的服务器必须处理的额外查询。另外在重复关键的事情。如果行已经存在,它基本上是一个UPDATE。所以只有当行中的其他列发生了变化时才这样做。否则,让自己多余的操作你的服务器必须处理。别忘了,你也摆脱了原子问题。 – fancyPants 2012-03-27 21:10:32

+0

理解,但REPLACE或者只比ON DUPLICATE KEY差,因为它将在两行中重写。我认为抓住错误,而INSERTING似乎是唯一可以接受的解决方案 – nemenems 2012-03-28 13:56:17

0

我看到它的方式,你有两个选择:

1)使用Lock TablesSELECT然后Insert。锁定桌子将确保您不会因竞争状态而结束。 2)如果您担心桌面锁,您可以执行列出的第一个选项:INSERT或更好,INSERT IGNORE。如果您使用INSERT IGNORE,则重复键异常将作为警告返回。

就我个人而言,我会尝试表锁,看看它是否工作。你的SELECT声明应该快速运行,因为它有一个唯一的密钥,所以我不会担心锁会减慢你的速度。

+0

锁定桌子肯定不是最好的解决方案,因为桌子锁真的很重。我的例子是一个研究案例。想象一下写密集型数据库的问题 – nemenems 2012-03-27 15:42:00