मान लीजिए कि मैं 1000 अनुरोध एक MySQL तालिका अद्यतन करने के लिए हमारे सर्वर पर प्राप्त की जा रही चला रहे हैं। इस स्थिति में डेडलॉक मुद्दे अनिवार्य रूप से होते हैं। हमने लेन-देन को डेडलॉक्स के लिए अनुशंसित करने के लिए पुनः प्रयास किया है लेकिन वे अभी भी होते हैं।MySQL InnoDB इंजन कतार डीबी ट्रिगर स्वचालित रूप से करता है?
हम नीचे कोई वैकल्पिक समाधान के साथ आ के बारे में सोच रहे हैं।
- बनाएं टेबल ए, बी, सी
- लिखें अनुरोध क्रमशः सर्वर के लिए आ रहा टेबल डी, अद्यतन करने के लिए एक या बी या सी
- में टेबल्स ए, बी और सी पर एक सम्मिलित ट्रिगर बनाएं जो सर्वर पर आने वाले 1000 अनुरोधों को सीधे तालिका डी को उजागर करने के बजाय तालिका डी में डेटा लिख देगा।
इसलिए हमारे प्रश्न जब ऐसा होता है और कई पंक्तियों टेबल ए, बी और सी में लिखा जाता है ए, बी और सी टेबल डी अद्यतन करने के लिए एक ही समय में सक्रिय हो सकता है टेबल्स पर अंतर्निहित ट्रिगर है
क्या MySQL InnoDB इंजन स्वचालित रूप से इन ट्रिगर्स को कतारबद्ध करता है या क्या हमें इसे हमारे कोड में संभालना होगा?
किसी भी मदद की बहुत सराहना की जाती है।
टेबल डी कि है अब इन सभी अनुरोधों द्वारा सीधे अपडेट किया जा रहा है और जहां गतिरोध इस तरह दिखता होता है।
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
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__);
}
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;
}
वहाँ एक क्लीनर तरीका यह गतिरोध से बचने के लिए है? यहां कुछ लॉग हैं जो हमारे पास हैं।
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
लाइन 83 PHP में अद्यतन विवरण है और 86 INSERT है। कृपया ध्यान रखें कि इस डेटा को प्रति सेकंड 5-8 लेनदेन की दर से इस तालिका में लिखा जा सकता है।
अतिरिक्त जानकारी
हर सम्मिलित करें और टेबल डी में अद्यतन एक ट्रिगर निष्पादित करता है कि अद्यतन टेबल एक्स और टेबल वाई इस के लिए तालिका डी बंद कर दिया रहने के लिए और इसलिए आने वाले अनुरोधों को एक हो जाता है एक कारण है के साथ गतिरोध?
अंत में समस्या आई लेकिन मुझे यकीन नहीं है कि इसे कैसे हल किया जाए। इसके बाद सम्मिलित करें और उसके बाद अद्यतन से चलाता टेबल डी तालिका जब वे ट्रिगर कर रहे हैं और इसलिए आने वाले अनुरोधों गतिरोध ताले पर। मैं क्यों इस बात का इतना यकीन है क्योंकि एक बार मैं इन ट्रिगर्स लॉग प्रवेश करने बंद कर दिया गिरा गतिरोध संदेशों उत्प्रेरक कोड की लॉग इन अन्यथा
स्निपेट है।
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
यह वह जगह है जहाँ मैं समझ में नहीं आता क्यों इन ट्रिगर्स टेबल डी पर एक ताला पकड़ होगा और न जाने किसी भी सम्मिलित/अपडेट समवर्ती होता है।
क्या हम सभी समस्याओं से बचेंगे यदि हम ट्रिगर छोड़ देते हैं और केवल काम करने के लिए PHP से एसपी को कॉल करते हैं?
क्या अपने लेनदेन की तरह लग रहे बनाने के लिए करना चाहते हैं? डेडलॉक करने के लिए, आपके पास 1 से अधिक लेन-देन होना चाहिए, जो पहले से ही एक पंक्ति अपडेट कर चुका है और दूसरी पंक्ति को अपडेट करने का प्रयास करता है, लेकिन उस पंक्ति को दूसरे लेनदेन द्वारा अपडेट किया गया था। सिमनल आवेषण, साथ ही साथ केवल 1 पंक्ति पर अपडेट, डेडलॉक का कारण नहीं बनेंगे। शायद आपको अपने अपडेट प्रश्नों को सीमित/सीमित करने की आवश्यकता है? –
@Darhazer लेनदेन के विवरण के साथ प्रश्न अद्यतन किया। आपका सहयोग सराहनीय है। – Aakash
क्या आपके पास v_user_email/i_adid पर अनुक्रमणिका है। यदि नहीं, तो है कि एक गतिरोध पैदा कर रहा है, अद्यतन क्वेरी सभी रिकॉर्ड को स्कैन करने के लिए है कारण –