为什么这两个SQL语句会导致操作死锁错误?

时间:2011-08-15 05:10:20

标签: python mysql

我有这张桌子:

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分支,然后这两个事务死锁?

1 个答案:

答案 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;
相关问题