2012-07-20 140 views
2

MySQL文档指出,在使用INSERT ... ON DUPLICATE KEY UPDATE时,插入记录时受影响的行值为1,如果更新现有记录,则值为2。MySQL:插入....在重复密钥更新:受影响的行== 3?

当更新记录时,我们得到受影响的行值为3,尽管我只是在通过使用来自Java的Connector-J的MySQL调用执行更新时才看到这一点;当我从MySQL Workbench调用存储过程时,我得到了预期的2行更新结果。

有没有人知道这可能意味着什么?这可能是一个Connector-J的annomely?我倾向于只用它来运行,但没有合理的解释,我就担心我的数据完整性(毕竟,这是检查受影响的行值的原因之一)。

MySQL服务器版本:5.1.57;连接器-J版本:5.1.7(爪哇1.6)

的附加细节: 这是所修改的表:

CREATE TABLE `UserContactProperty` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `UserContactId` int(11) NOT NULL, 
    `Property` varchar(45) NOT NULL, 
    `Value` tinytext, 
    `Date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `Contact-Property` (`UserContactId`,`Property`), 
    KEY `FK_UserContact` (`UserContactId`), 
    CONSTRAINT `FK_UserContact` FOREIGN KEY (`UserContactId`) REFERENCES `UserContact` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=28685 DEFAULT CHARSET=latin1 

执行插入/更新该存储的过程如下:

CREATE PROCEDURE `setUserContactProperty`(
    UID VARCHAR(50), 
    CID INT, 
    Prop VARCHAR(45), 
    Val TINYTEXT 
) 
BEGIN 
    INSERT INTO UserContactProperty (UserContactId, Property, Value) 
     VALUES (CID, Prop, Val) 
     ON DUPLICATE KEY UPDATE Value = Val, Date = CURRENT_TIMESTAMP; 
END 
+0

您可以打开常规日志记录或将“profileSQL = true”添加到您的JDBC连接字符串以准确查看要发送到服务器的内容。 – 2012-07-20 03:27:39

回答

2

这似乎是一个错误。请查看以下链接:

http://bugs.mysql.com/bug.php?id=46675

由于有报道,在生成的密钥列表是错误的,计数错误太多错误是另一错误。 (第二个bug来自这里http://slava-technical.blogspot.co.il/2011/05/mysql-on-duplicate-key-update-breaks.html

我认为你需要找到一个解决方法。可能在插入之前通过查询数据库来查看该键是否存在。或者插入并捕获重复的关键异常,然后在该情况下进行更新。

+0

不要忘记将这些查询包装到一个事务中,所以在你首先检查存在之后,你不要跳过并行插入。这样做,请确保您的存储引擎支持交易(例如,MyISAM不支持)。另外,请确保通过其他方式锁定(例如,通过一次只能处理一个服务器的请求) – spacediver 2012-07-20 05:21:07

+0

感谢您提供错误报告链接 - 非常翔实!对于解决方法,我认为我会用我的第一本能:把3作为有效的返回值,并将其作为2.的同义词。在bug文档中没有任何地方表明除3以外的值是可能的(除了在较旧的服务器版本中,这与我无关)。 – 2012-07-20 17:29:26