2011-08-17 12 views
12

में एक जोड़ता है, मैं एक साधारण हिट काउंटर के साथ उन सभी http_user_agents का ट्रैक रखता हूं जो मुझे देखते हैं। नीचे डीबी में http_user_agent डालें, यह फ़ील्ड केस असंवेदनशील है और अद्वितीय है। तो जब हम इसे डालने का प्रयास करते हैं और इसे एक डिप्लिकेट कुंजी मिलती है, तो यह हिट फ़ील्ड में 1 जोड़ती है।MySQL INSERT .... डिप्लिकेट अपडेट पर - ऑटोइनक्रिएटमेंट

समस्या यह है कि मेरा ऑटो वृद्धि क्षेत्र अभी भी बढ़ता है भले ही हमने कोई फ़ील्ड डाला न हो। मेरे द्वारा इसे कैसे रोका जा सकता है?

CREATE TABLE `tblRefHttpUsersAgent` 
(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
`http_users_agent` varchar(255) NOT NULL, 
`hits` int(20) unsigned NOT NULL DEFAULT '1', 
`created_ts` datetime NOT NULL, 
`activity_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
PRIMARY KEY (`id`), 
UNIQUE KEY `http_users_agent` (`http_users_agent`) 
) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; 
+0

संभावित रूप से संबंधित: http://stackoverflow.com/questions/2634152/getting-mysql-insert-id-while-using-on-duplicate-key-update-with-php –

उत्तर

18

INSERT ... ON DUPLICATE KEY UPDATE को इनो डीबी के AUTO_INCREMENT हैंडलिंग के उद्देश्यों के लिए "मिश्रित मोड डालने" के रूप में वर्णित किया गया है। मिश्रित-मोड आवेषण मूल रूप से हैं जहां अधिकतम आवश्यक AUTO_INCREMENT मानों की संख्या ज्ञात है, लेकिन की राशि वास्तव में आवश्यक होगी नहीं है। MySQL docs में वर्णित के रूप

मिश्रित मोड आवेषण, विशेष रूप से डिफ़ॉल्ट रूप से नियंत्रित किया हो:

...for “mixed-mode inserts”... InnoDB will allocate more auto-increment values than the number of rows to be inserted. However, all values automatically assigned are consecutively generated (and thus higher than) the auto-increment value generated by the most recently executed previous statement. “Excess” numbers are lost.

आप InnoDB का उपयोग कर रहे हैं, तो आपके विकल्प हैं:

  1. INSERT ... ON DUPLICATE KEY UPDATE से बचें।
  2. पैरामीटर को 0 पर सेट करें, "पारंपरिक" ऑटोइनक्रिकमेंट लॉक मोड के लिए, जो गारंटी देता है कि सभी INSERT कथन AUTO_INCREMENT कॉलम के लिए निरंतर मान असाइन करेंगे। हालांकि, यह कथन के दौरान लॉक करके पूरा किया जाता है, इसलिए इस सेटिंग से जुड़े प्रदर्शन हानि होती है।
  3. (अनुशंसित) AUTO_INCREMENT कॉलम में अंतराल को अनदेखा करें।

नोट: AUTO_INCREMENT हैंडलिंग MyISAM के तहत पूरी तरह से अलग है, जो इस व्यवहार को प्रदर्शित नहीं करता है।

+0

रनटाइम के दौरान 'innodb_autoinc_lock_mode' को सेट करने का प्रयास करने से मुझे त्रुटि मिली: 'SQLSTATE [HY000]: सामान्य त्रुटि: 1238 परिवर्तनीय' innodb_autoinc_lock_mode 'केवल पढ़ने योग्य चर है', इस पर विचार करते हुए कि मुझे इसे थोक यूपीएसईआरटी के लिए चाहिए, क्योंकि इंडिवी दोहरी आवेषण बहुत धीमी हैं। मैं विकल्प 1, 2 या 3 का उपयोग नहीं कर सकता, क्योंकि अंतराल संख्याओं को autoinc आईडी को जला देता है। क्या आप एक और समाधान सुझा सकते हैं? –

+0

यदि मैं PostgreSQL का उपयोग करता हूं तो ऑटो-वृद्धि फ़ील्ड में समान अंतराल मनाया जाएगा? –

6

भंडारण इंजन एक पंक्ति सम्मिलित करने से पहले AUTO_INCREMENT मूल्य को बढ़ा चाहिए:

$sql = "INSERT INTO `db_agency_cloud`.`tblRefHttpUsersAgent` SET `http_users_agent` = :UsersAgent, `created_ts` = NOW() ON DUPLICATE KEY UPDATE `hits` = `hits` + 1"; 

यहाँ टेबल संरचना है। यह नहीं पता कि सम्मिलन उस बिंदु पर अभी तक असफल हो जाएगा या नहीं। यह केवल वृद्धि को वापस नहीं ले सकता है क्योंकि अन्य कनेक्शनों पर एक साथ अन्य प्रविष्टियां हो सकती हैं। यह सामान्य व्यवहार है और कुछ ऐसा नहीं जो आपको करना चाहिए (या कर सकते हैं)। AUTO_INCREMENT का उद्देश्य अद्वितीय पहचानकर्ता प्रदान करना है, संख्याओं का एक अखंड अनुक्रम नहीं।

+0

हाँ लेकिन मैं दो बनाना नहीं चाहता था डेटाबेस को कॉल करता है। मैं उन समाधानों की उम्मीद कर रहा था जो इसे छोड़ देते थे। मैं शायद एक बयान के बारे में सोच रहा हूँ। फिर यह देखने के लिए कि क्या यह रिकॉर्ड डालना या अपडेट करना चाहिए, डेटाबेस स्तर पर जांच कर रहा है। –

+2

आपको कोई अतिरिक्त कॉल करने की ज़रूरत नहीं है। आईडी में अंतर के साथ कुछ भी गलत नहीं है। आपको यहां ठीक करने की कोई समस्या नहीं है। –

+0

+1: और दिलचस्प! ठीक है, मैं grok _why_ यह होता है (आपके उत्तर के लिए धन्यवाद); हालांकि, यह निश्चित रूप से दुर्भाग्यपूर्ण लगता है।यह बिल्कुल सहज नहीं है और मैं इसे ** बग ** (या तो SQL मानक में, या MySQL में) पर भी विचार करता हूं ... यहां तक ​​कि जब यह हमेशा होता है जिसे हमेशा 'WONTFIX' के रूप में हल किया जाएगा। –

1

दुर्भाग्यवश यदि आप ऑटो-वृद्धि आईडी को प्रभावित नहीं करना चाहते हैं तो समाधान एप्लिकेशन स्तर पर है। पहले SELECT करें और परिणाम पंक्तियों की गणना करें। यदि 0 परिणाम, INSERT डेटा। यदि 0 से अधिक UPDATE उस पंक्ति से अधिक है।

+0

हाँ, लेकिन मैं डेटाबेस में दो कॉल नहीं करना चाहता था। मैं उन समाधानों की उम्मीद कर रहा था जो इसे छोड़ देते थे। मैं शायद एक कथन का विचार कर रहा हूं। फिर डेटाबेस स्तर पर जांच कर यह देखने के लिए कि क्या इसे रिकॉर्ड डालना या अपडेट करना चाहिए। –

संबंधित मुद्दे