MySql错误>超过锁定等待超时;尝试重新启动事务SQLState:41000 VendorError:1205

时间:2013-02-20 11:15:36

标签: mysql locking

多年来我一直在讨论这个问题,而且从来没有能够深入到底。我不知道是什么导致这些锁。

错误是:Lock wait timeout exceeded; try restarting transaction SQLState: 41000 VendorError: 1205

SQL语句是在事务中运行的单个insert语句。所有刀片都是这种形式,所以没有批量插入,也没有混合模式插入等。

INSERT INTO attachment( id, entityid, entitytype , addeduserid , deleteduserid , fullpath , filename, status, creationdate, lastupdated, deletiondate, hasfile,notes,history,type,mimeinfo,archivedby,archivedon, referencedate,changedby,changedon ) values (0,0,2,360,null,NULL,NULL,1,'2013-02-20 08:45:31','2013-02-20 08:45:31',NULL,0,NULL,'20/02/2013 08:45:UserA:File uploaded internally. <br>',0,NULL,null,NULL,NULL,null,NULL);

系统配置: Mysql版本:'服务器版:5.1.61源代码发布'(在Redhat上)

存储:INNODB

INNODB相关配置(部分由my.cnf编辑):

innodb_file_per_table=1
innodb_buffer_pool_size=3G
innodb_additional_mem_pool_size=20M
innodb_log_file_size=512M
innodb_log_files_in_group=2
innodb_log_buffer_size=16M
innodb_support_xa=1
innodb_doublewrite=1
innodb_thread_concurrency=0
innodb_flush_log_at_trx_commit=2
innodb_autoinc_lock_mode=2**
innodb_rollback_on_timeout=1
innodb_locks_unsafe_for_binlog=1**
thread_cache_size=8
query_cache_size=256M
query_cache_limit=4M
table_cache=2048
table_definition_cache=1024
tmp_table_size=512M
max_heap_table_size=512M
transaction-isolation=READ-COMMITTED**
innodb_table_locks=0**
innodb_lock_wait_timeout=50**

**这些是针对这个问题专门添加的。

一般来说:

系统(即每个具有相同数据库结构的6个应用程序实例都运行在单个mysql实例上)可以正常运行数天,然后可以运行Lock Waits开始运行并且通常会使它们出现在组中在一天中的这段时间。每个错误都会重复出现,因为一旦失败,我会再次尝试,通常重新尝试将失败。我已配置重试4次。通常,锁只会出现在几个不同的表中。

今天特定的问题实例:

今天早上在attachment桌子上,自昨晚以来桌面上没有插入。自前一天晚上以来,桌面上也没有任何更新。 如果锁与执行更新和插入的其他用户无关,那么某些select语句是否会导致锁定?我试图确保所有选择语句都使用attachment_general_index

由于我主要是在几个不同的表上得到这个 - 这是这个表的结构。

CREATE TABLE `attachment` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`entityid` int(10) unsigned DEFAULT NULL,
`entitytype` tinyint(3) unsigned NOT NULL DEFAULT '0',
`addeduserid` int(10) unsigned NOT NULL,
`deleteduserid` int(10) unsigned DEFAULT NULL,
`fullpath` varchar(255) DEFAULT NULL,
`filename` varchar(255) DEFAULT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`creationdate` varchar(40) DEFAULT NULL,
`lastupdated` varchar(40) DEFAULT NULL,
`deletiondate` varchar(40) DEFAULT NULL,
`hasfile` tinyint(3) unsigned NOT NULL DEFAULT '0',
`notes` text,
`history` text,
`type` tinyint(3) unsigned DEFAULT '0',
`lastupdatedby` int(10) DEFAULT '0',
`lastupdatedinfo` varchar(255) DEFAULT NULL,
`mimeinfo` varchar(255) DEFAULT NULL,
`archivedby` int(10) unsigned DEFAULT NULL,
`archivedon` varchar(40) DEFAULT NULL,
`referencedate` varchar(40) DEFAULT NULL,
`changedby` int(10) unsigned DEFAULT NULL,
`changedon` varchar(40) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `attachment_addeduserid_fkey` (`addeduserid`),
KEY `attachment_deleteduserid_fkey` (`deleteduserid`),
KEY `attachment_archivedby_fkey` (`archivedby`),
KEY `attachment_changedby_fkey` (`changedby`),
KEY `attachment_general_index` (`entitytype`,`entityid`,`status`,`type`),
CONSTRAINT `attachment_ibfk_1` FOREIGN KEY (`addeduserid`) REFERENCES `user` (`id`),
CONSTRAINT `attachment_ibfk_2` FOREIGN KEY (`deleteduserid`) REFERENCES `user` (`id`),
CONSTRAINT `attachment_ibfk_3` FOREIGN KEY (`archivedby`) REFERENCES `user` (`id`),
CONSTRAINT `attachment_ibfk_4` FOREIGN KEY (`changedby`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3619 DEFAULT CHARSET=latin1$$

我已经附上了最近的SHOW INNODB状态,这是从今天起,从昨天开始就没有锁等待。我不明白所有这些输出,但主要的是锁似乎永远不会出现在这里。我假设他们没有归类为死锁?

https://docs.google.com/document/d/1Hslf2B594n8ofAUYxN54Gh8FrSCIFNGGMtthVI_Lv4k/pub

这个问题只有死锁区才有意思吗?如果还有其他区域,我会尽力收集并提供。

任何帮助都将不胜感激。

尼克

2 个答案:

答案 0 :(得分:6)

我想与那些在交易超时中摸不着头脑的人分享我的“Eureka”时刻,并且发现没有任何建议的服务器配置更改有帮助。

我正在挣扎到我正在认真考虑重新编写我的一些应用程序,这样我才能适应交易超时(全世界都听到了集体呻吟声)。

我对于从我的业务交易中丢失任何东西都很偏执,因此我运行一个cron作业,每天10分钟(这是双重复制的顶部)完成一个完整的mysqldump。

我发现mysqldump占用了服务器,锁定了表,并且几乎禁止使用数据库进行任何其他操作。当我发现事务失败与mysqldump运行时间一致时,我的Eureka时刻到来了。

长话短说,有3个命令行选项可以阻止mysqldump杀死你的服务器。这些是

  1. - 单笔交易
  2. - 快速
  3. - 锁定表=假
  4. 非常感谢CA3LE @ How can I slow down a MySQL dump as to not affect current load on the server?能够启发我。

答案 1 :(得分:3)

(这应该是评论,但我的文字太多了,需要格式化)。

我认为这与described at的问题非常相似:

  1. 一个事务在表的末尾有一个锁。
  2. 第二个交易锁定了大部分表格。
  3. 第一个事务尝试更新/插入第二个事务持有的锁。这失败了,因此选择了其中一个交易。
  4. 感谢您发布show status。你是对的,所显示的死锁似乎与你所询问的表没有关系,但它看起来与Xaprb的那个看起来相同。

      

    这个问题只有死锁区才有意思吗?

    是的,确切的部分是:

    Transaction 1
    
    UPDATE operative SET  lastupdated='2013-02-19 17:12:44'=N<EDITED> RECORD LOCKS space id 1789 page no 3622 n bits 112  index `PRIMARY` of table `<EDITED> `.`operative` trx id 0 233901602  lock_mode X locks rec but not gap waiting
    
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1789 page no 3622 n bits 112 index `PRIMARY` of table `<EDITED> `.`operative`  trx id 0 233901602 lock_mode X locks rec but not gap waiting
    
    
    Transaction 2
    
    INSERT INTO opdate(operativeId,opdate,updatingUser,dategroup,type,notes,lastupdated) values (....) RECORD LOCKS space id 1789 page no 3622 n bits 112 index `PRIMARY` of table `<EDITED> `.`operative`  trx id 0 233901603 lock mode S locks rec but not gap
    
    
    *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 830 page no 112 n bits 808  index `opdate_unique` of table `<EDITED> `.`opdate` trx id 0 233901603 lock mode S waiting Record lock, heap no 739 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
    

    这与xaprb中列出的问题非常相似。即

    1. 事务2已对表进行了插入,现在对主键进行了锁定。
    2. 事务1正在执行表扫描以执行更新,并且正在等待对该主键的锁定。
    3. 事务2正在尝试进行另一次插入,并且需要获取锁定但是因为事务1已经拥有它而被禁止这样做(我实际上是在猜测那里,因为你对表名进行了模糊处理)。
    4. 我建议首先修复此死锁,并尝试解决您所问的问题。

      实际上,我认为您的问题可能不会出现在INNODB状态中。您将收到错误代码1205 - 这是ER_LOCK_WAIT_TIMEOUT,而不是错误1213 ER_LOCK_DEADLOCK。因此,虽然你实际上有一个死锁,但它并没有被归类为这样。

      我认为如果您在问题发生时可以执行SHOW ENGINE INNODB STATUS,那么即使它们没有显示为最新的死锁,您也应该能够看到已停止的事务上的锁定。