我有这张桌子:
CREATE TABLE `notify` (
`id` int(11) NOT NULL auto_increment,
`notify_type` char(1) NOT NULL,
`notify_id` int(10) unsigned NOT NULL,
`create_time` timestamp NOT NULL default '0000-00-00 00:00:00',
`user` int(10) unsigned NOT NULL,
`update_time` timestamp NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `notify_id` (`notify_id`,`notify_type`,`user`),
KEY `Index_time` (`create_time`),
KEY `user_update` (`user`,`update_time`)
)
和两个连续执行然后一起执行的SQL查询
if user_id:
insert into notify (notify_type,notify_id,user,create_time)
values (%s,%s,%s,CURRENT_TIMESTAMP)
ON DUPLICATE KEY UPDATE update_time=update_time, (type, id, user_id)
update notify set update_time=NOW() where notify_type = %s
and notify_id =%s and user!=%s,(type, id, user_id)
else:
update reply_notify set update_time=NOW() where notify_type = %s
and notify_id =%s, (type, id)
commit()
经常导致
OperationalError:(1213,'尝试获取锁定时发现死锁;尝试重启事务')
有人能帮助我找出原因吗?我已经查阅了MySQL文档,我怀疑有一些与ON DUPLICATE KEY UPDATE
子句相关的东西,但我仍然无法弄明白。
可能是某些代码执行到if分支,而其他代码执行到else分支,然后这两个事务死锁?
答案 0 :(得分:1)
根据MySQL's doc,您的查询看起来很好。但是a bug可能是相关的。
您可以尝试切换表格所使用的引擎,在5.0中您可以尝试BDB (Berkeley DB)但现在不支持,否则我担心最好的选择是MyISAM。
或者,在插入周围放置LOCK TABLES ... UNLOCK TABLES
可以解决问题。
如果做不到这一点,您可以尝试在整个块周围放置锁定表(包括更新),看看是否真的会给您带来麻烦。
请记住,表锁定通常不利于性能,MyISAM不是为频繁更新而设计的,但您可能没有太多选择。
lock tables notify write;
insert into notify (notify_type,notify_id,user,create_time)
values (%s,%s,%s,CURRENT_TIMESTAMP)
ON DUPLICATE KEY UPDATE update_time=update_time, (type, id, user_id);
unlock tables;