Aak*_*ash 5 mysql triggers deadlock innodb
假设我在服务器上收到1000个请求来更新单个MySQL表.在这种情况下不可避免地会出现死锁问题.我们已经重新发布了针对死锁建议的事务,但它们仍然存在.
我们正在考虑在下面提出替代解决方案.
所以我们的问题是当这种情况发生并且多行被写入表A,B和C时,表A,B和C上的底层触发器可能同时触发以更新表D.
MySQL InnoDB引擎是否会自动对这些触发器进行排队,还是我们必须在代码中处理这个问题?
任何帮助深表感谢.
现在所有这些请求直接更新的表D以及发生死锁的位置如下所示.
v_user_email varchar(60) NO PRI
v_device_IMEI varchar(40) NO PRI
i_adid int(11) NO PRI
i_impressions int(4) YES 0
dt_pulllogdttm datetime NO
c_created_by char(15) NO
dt_created_on datetime NO
c_modified_by char(15) YES
dt_modified_on datetime YES
Run Code Online (Sandbox Code Playgroud)
在此表中插入/更新行的PHP如下所示.您将看到我们尝试将事务发布3次,如果它由于死锁而失败但是有些事务甚至失败并且由于死锁而导致日志显示.
$updateQuery = "UPDATE tb_ad_pull_log SET i_impressions = (i_impressions + 1), dt_pulllogdttm = SYSDATE(), c_modified_by = '$createdBy', dt_modified_on = SYSDATE() WHERE v_user_email = '$email' AND i_adid = $adId";
if(ExecuteDeadLockQuery($updateQuery, "UPDATE", __LINE__) == 0) // If there is no record for this ad for the user, insert a new record
{
$insertQuery = "INSERT INTO tb_ad_pull_log VALUES('$email', '$device_IMEI', $adId, 1, SYSDATE(), '$createdBy', SYSDATE(), NULL, NULL)";
ExecuteDeadLockQuery($insertQuery, "INSERT", __LINE__);
}
Run Code Online (Sandbox Code Playgroud)
ExecuteDeadLockQuery函数看起来像这样 -
function ExecuteDeadLockQuery($query, $activity, $lineNumber)
{
global $errorLoggingPath;
$maxAttempts = 3;
$currentTry = 1;
$noOfAffectedRows = -1;
while($currentTry <= $maxAttempts)
{
$currentTry++;
mysql_query($query);
if( mysql_errno() <> 0 ) // If error occured
{
continue;
}
else
{
$noOfAffectedRows = mysql_affected_rows();
break;
}
}
if($noOfAffectedRows == -1) // Query never executed successfully
{
LogError($activity . " failed in tb_ad_pull_log: " . mysql_error(), __FILE__, $lineNumber , $errorLoggingPath);
}
return $noOfAffectedRows;
}
Run Code Online (Sandbox Code Playgroud)
有没有更清洁的方法来避免这种僵局?这是我们的一些日志.
ERROR: 08-21-2011 14:09:57 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:09:57 INSERT failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 86
ERROR: 08-21-2011 14:09:57 INSERT failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 86
ERROR: 08-21-2011 14:09:57 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:09:57 INSERT failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 86
ERROR: 08-21-2011 14:09:57 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:09:59 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:09:59 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:10:01 UPDATE failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 83
ERROR: 08-21-2011 14:10:01 INSERT failed in tb_ad_pull_log: Deadlock found when trying to get lock; try restarting transaction LINE 86
Run Code Online (Sandbox Code Playgroud)
第83行是PHP中的UPDATE语句,86是INSERT.请记住,这些数据可以每秒5-8个事务的速率写入此表.
附加信息
对表D中的每个INSERT和UPDATE执行一个更新TABLE X和TABLE Y的触发器.这是表D保持锁定的原因,因此传入的请求会出现死锁吗?
终于得到了问题,但我不知道如何解决它.表D上的AFTER INSERT和AFTER UPDATE触发器在触发表时会锁定表,因此传入的请求会死锁.为什么我这么肯定是因为一旦我删除了这些触发器,日志就会停止记录死锁消息
触发器代码的片段.
CREATE DEFINER=CURRENT_USER TRIGGER tuadmin.t_update_CPM_updateBalance
AFTER UPDATE
ON tb_ad_pull_log
FOR EACH ROW
BEGIN
DECLARE `cpm_value` decimal(10,4);
DECLARE `clientid` int(4);
/* Execute the below block if the requested ad is not the default ad */
IF NEW.i_adid <> 1 THEN
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
//do updates to TABLE X and Y logic
END
Run Code Online (Sandbox Code Playgroud)
这是我不明白为什么这些触发器会锁定表D并且不允许任何插入/更新同时发生的地方.
如果我们删除触发器并从PHP调用SP来完成工作,这会避免所有问题吗?
| 归档时间: |
|
| 查看次数: |
2154 次 |
| 最近记录: |