MySQL में लॉक किए बिना चयन करने का कोई तरीका?


126

प्रश्न:

SELECT COUNT(online.account_id) cnt from online;

लेकिन ऑनलाइन तालिका को एक घटना से भी संशोधित किया जाता है, इसलिए अक्सर मैं लॉक को चलाकर देख सकता हूं show processlist

क्या MySQL में कोई व्याकरण है जो चुनिंदा कथन को ताले का कारण नहीं बना सकता है?

और मैं ऊपर उल्लेख करना भूल गया कि यह एक MySQL दास डेटाबेस पर है।

बाद मैं my.cnf:transaction-isolation = READ-UNCOMMITTED गुलाम में जोड़ा त्रुटि के साथ पूरा करेगा:

त्रुटि 'बाइनरी लॉगिंग संभव नहीं है। संदेश: InnoDB में लेन-देन का स्तर 'READ-UNCOMMITTED' क्वेरी के लिए बिनॉल मोड 'स्टेटमेंट' के लिए सुरक्षित नहीं है।

तो, क्या ऐसा करने का एक संगत तरीका है?


3
दूसरों के लिए जो इस प्रश्न का सामना करते हैं और उनकी तालिकाओं पर ताले के साथ एक कठिन समय होता है: mySQL आंतरिक रूप से ताले का उपयोग कैसे करता है यह भंडारण इंजन पर निर्भर करता है। नीचे @zombat द्वारा उत्तर पढ़ें।
साइमन फोर्सबर्ग

जवाबों:


169

"MYSQL विद NOLOCK" शीर्षक से एक लेख मिला

https://web.archive.org/web/20100814144042/http://sqldba.org/articles/22-mysql-with-nolock.aspx

MS SQL सर्वर में आप निम्न कार्य करेंगे:

SELECT * FROM TABLE_NAME WITH (nolock)

और MYSQL समकक्ष है

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

संपादित करें

माइकल मिओर ने निम्नलिखित सुझाव दिए (टिप्पणियों से)

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
COMMIT ;

54
भविष्य के पाठकों के लिए बस एक नोट जिसे आप समाप्त करना चाहते हैं SESSIONऔर इस तरह लेन-देन का स्तर केवल अगले लेनदेन पर लागू होता है। फिर, बस ऊपर दिए गए तीसरे कथन को बदलें COMMIT। यह इस मामले में एक शून्य होगा, लेकिन लेन-देन को समाप्त करने और डिफ़ॉल्ट अलगाव स्तर पर रीसेट करने का एक साइड-इफेक्ट है।
माइकल मिओर

3
बस एक नोट, वह लिंक मर चुका है ... :(
लोंदा

5
क्षमा करें, लेकिन मुझे यहाँ InnoDB और MyISAM के बीच बहुत महत्वपूर्ण अंतरों का उल्लेख नहीं करने के लिए इस उत्तर को रद्द करना होगा। जैसा कि @omg द्वारा ऊपर कहा गया है, यह InnoDB के लिए काम करेगा लेकिन MyISAM तालिकाओं के लिए नहीं।
साइमन फोर्सबर्ग

4
@ क्रेग यह निश्चित रूप से गलत है कि MyISAM SELECT क्वेरीज़ के दौरान READ ताले जारी नहीं कर रहा है - इन लॉक का विरोध कर रहे हैं और InnoDB का विरोध कर रहे हैं, ताले लॉक हैं, निष्पादन के दौरान सभी अनुरोधित WRITE ताले और सभी बाद के प्रश्नों को ब्लॉक कर रहे हैं । मूल प्रश्न InnoDB के बारे में प्रतीत होता है, हालांकि और अलगाव के स्तर MyISAM के लिए भी अस्तित्वहीन हैं - कथन राज्य के लिए दस्तावेज़SET TRANSACTION : "यह कथन हस्तांतरण अलगाव स्तर सेट करता है, जिसका उपयोग InnoDB तालिकाओं पर संचालन के लिए किया जाता है।"
पर्यायवाची- dj

1
बिंदु ने मान लिया। :-) मैं वास्तव में MyISAM बनाम InnoDB के लॉकिंग व्यवहार को संदर्भित करने की कोशिश कर रहा था। ये अलगाव स्तर-आधारित समाधान MyISAM पर लागू नहीं होते हैं, जो लेनदेन योग्य नहीं है, इसलिए यह एक साधारण टेबल लॉक का उपयोग करता है । MyISAM UPDATE और DELETE को टेबल लॉक के क्लियर होने का इंतजार करना है, इसलिए राइट रिक्वेस्ट के बाद किसी भी सेलेक्ट की कतार को राइट खत्म होने तक ब्लॉक कर दिया गया है। MyISAM में कोई "गंदी रीडिंग" नहीं है और कोई भी तरीका नहीं है कि ज्यादातर राइट्स समवर्ती रूप से रीड्स के साथ हो सकें, इस प्रकार किसी भी टिप्पणी के बारे में यहाँ कोई पकड़ नहीं है "MyISAM को संबोधित करने में विफल।" मुझे लगता है कि मैं क्या कर रहा था। :-)
क्रेग

24

यदि तालिका InnoDB है, तो http://dev.mysql.com/doc/refman/5.1/en/innodb-consistent-read.html देखें - यह चयनों के लिए संगत-रीड (नो-लॉकिंग मोड) का उपयोग करता है " निर्दिष्ट मोड में अद्यतन या लॉक के लिए निर्दिष्ट न करें यदि innodb_locks_unsafe_for_binlog विकल्प सेट है और लेनदेन का अलगाव स्तर SERIALIZABLE के लिए सेट नहीं है। इस प्रकार, चयनित तालिका से पढ़ी गई पंक्तियों पर कोई लॉक सेट नहीं होता है "।


16

उपयोग

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

संस्करण 5.0 डॉक्स यहां हैं

संस्करण 5.1 डॉक्स यहां हैं


2
धन्यवाद, मुझे लगता है कि यह निकट है, लेकिन यह कथन कब तक प्रभावी होगा? मैं एक PHP कार्यक्रम में इस बयान का उपयोग करने के लिए जा रहा हूँ, और सबसे अच्छी रीसेट लेनदेन अलगाव स्तर स्वचालित रूप से एक बार क्वेरी समाप्त होना चाहिए
OMG

14

आप MySQL मैनुअल के इस पृष्ठ को पढ़ना चाह सकते हैं । किसी तालिका को लॉक कैसे किया जाता है यह इस पर निर्भर करता है कि यह किस प्रकार की तालिका है।

MyISAM बहुत अधिक पढ़ने की गति को प्राप्त करने के लिए टेबल लॉक का उपयोग करता है, लेकिन यदि आपके पास UPDATE स्टेटमेंट की प्रतीक्षा है, तो भविष्य के चुनाव UPDATE के पीछे कतार में लग जाएंगे।

InnoDB टेबल पंक्ति-स्तर लॉकिंग का उपयोग करते हैं, और आपके पास एक UPDATE के पीछे पूरी तालिका लॉक नहीं होगी। InnoDB से जुड़े अन्य प्रकार के लॉकिंग मुद्दे हैं, लेकिन आप इसे अपनी आवश्यकताओं के अनुसार पा सकते हैं।


1
क्या MyISAM तालिकाओं के लिए "ट्रांसमिटेशन इंसॉल्वेंसी लीव्ड रीड अनकमोडेड" काम करेगा?
०g

5
MyISAM टेबल किसी भी रूप में लेनदेन का समर्थन नहीं करते हैं। एक लेनदेन क्वेरी MyISAM तालिका पर चलेगी, इसलिए आपके द्वारा ऊपर उल्लेखित क्वेरी निष्पादित होगी, लेकिन इसका कोई प्रभाव नहीं है।
zombat

1
तो फिर मैं MyISAM के मामले में SELECTS की कतार से बचने के लिए क्या कर सकता हूँ?
OMG

6
MyISAM के मामले में SELECTS की कतार से बचने के लिए मैं क्या कर सकता हूं? निर्दोष पर स्विच करें। MyISAM हर क्वेरी के लिए टेबल लेवल लॉक का उपयोग करता है। यह प्रमुख दोष है।
फ्रैंक किसान

2

आपके टेबल प्रकार के आधार पर, लॉकिंग अलग तरीके से प्रदर्शन करेगा, लेकिन ऐसा एक सेलेक्ट काउंट होगा। MyISAM तालिकाओं के लिए एक सरल चयन गणना (*) तालिका से तालिका को लॉक नहीं करना चाहिए क्योंकि यह रिकॉर्ड गणना को खींचने के लिए मेटा डेटा तक पहुंचती है। इनोडब को अधिक समय लगेगा क्योंकि रिकॉर्ड को गिनने के लिए स्नैपशॉट में तालिका को पकड़ना होगा, लेकिन यह लॉकिंग का कारण नहीं होना चाहिए।

आपको कम से कम 1 (डिफ़ॉल्ट) पर समवर्ती_संग्रह सेट होना चाहिए। फिर, यदि तालिका को भरने के लिए डेटा फ़ाइल में कोई "अंतराल" नहीं है, तो आवेषण को फ़ाइल में जोड़ा जाएगा और चयन और INSERTs एक साथ MyISAM तालिकाओं के साथ हो सकते हैं। ध्यान दें कि एक रिकॉर्ड को हटाने से डेटा फ़ाइल में एक "गैप" हो जाता है जो भविष्य के आवेषण और अपडेट से भरा होने का प्रयास करेगा।

यदि आप शायद ही कभी रिकॉर्ड हटाते हैं, तो आप समवर्ती_संग्रह को 2 के बराबर सेट कर सकते हैं, और आवेषण हमेशा डेटा फ़ाइल के अंत में जोड़े जाएंगे। फिर चयन और आवेषण एक साथ हो सकते हैं, लेकिन आपकी डेटा फ़ाइल कभी भी छोटी नहीं होगी, चाहे आप कितने भी रिकॉर्ड हटा दें (सभी रिकॉर्डों को छोड़कर)।

नीचे की रेखा, यदि आपके पास एक टेबल पर बहुत सारे अपडेट, आवेषण और चयन हैं, तो आपको इसे InnoDB बनाना चाहिए। आप स्वतंत्र रूप से एक प्रणाली में तालिका प्रकार मिश्रण कर सकते हैं।


1

mysql में गंदे पढ़ने को सक्षम करने का एक और तरीका है संकेत जोड़ना: LOCK IN SHARE MODE

SELECT * FROM TABLE_NAME LOCK IN SHARE MODE; 

"यदि ऑटोकॉमिट 1 पर सेट है, तो LOCK IN SHARE MODE और FOR UPDATE क्लॉस का कोई प्रभाव नहीं है।" ... और autocommit = 1 डिफ़ॉल्ट है
मार्टिन Zvarík

0

से इस संदर्भ:

यदि आप LOCK TABLES के साथ स्पष्ट रूप से टेबल लॉक प्राप्त करते हैं, तो आप टेबल लॉक होने के दौरान समवर्ती आवेषण करने के लिए अन्य सत्रों को सक्षम करने के लिए READ लॉक के बजाय READ LOCAL लॉक का अनुरोध कर सकते हैं।


0

चयन आम तौर पर किसी भी लॉकिंग को नहीं करते हैं जो आप इनोबीडी तालिकाओं पर ध्यान देते हैं। डिफॉल्ट ट्रांजेक्शन आइसोलेशन स्तर का मतलब है कि सामान को लॉक न करना।

बेशक विवाद अभी भी होता है।


1
मुझे पता है कि यह पोस्ट पुरानी है, लेकिन यह उत्तर बहुत सामान्य है, और केवल कभी-कभी सच है। Dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html देखें । अलगाव स्तर के आधार पर, ताले निश्चित रूप से रीड्स के लिए अधिग्रहित किए जाते हैं । विशेष रूप से, इस मामले में, पोस्टर प्रतिकृति डेटाबेस के साथ काम कर रहा है और स्पष्ट रूप से कहा गया है कि वह show processlistवास्तव में ताले को देखने के लिए उपयोग कर सकता है । इसलिए यह मान लेना सुरक्षित है कि वास्तव में ताले लगे हैं।
क्रेग

1
जवाब हमेशा सच होता है। बेशक, कुछ लॉकिंग है - इनोडोड के अंदर कुछ आंतरिक म्यूटेक्स जो कि उपयोग किए जाते हैं (उदाहरण के लिए इनोडोड बफर पूल म्यूटेक्स)। अधिकांश उपयोगकर्ता इन तालों के बारे में ध्यान नहीं देते हैं या नोटिस करते हैं और वे सामान्य रूप से केवल DDL परिचालनों के दौरान (जैसे कि यदि आपके पास 16G बफर पूल है और किसी अन्य थ्रेड में "ड्रॉप टेबल" करते हैं)। लेकिन यह डिफ़ॉल्ट रूप से किसी भी पंक्ति-ताले को नहीं लेता है। मेरा मतलब यही था। हालांकि उत्तर काफी अस्पष्ट था।
मार्क

1
हमेशा हमेशा? क्या होगा यदि ट्रांजेक्शन आइसोलेशन लेवल सीरियल करने योग्य है, या सेलेक्ट स्टेटमेंट LOCK IN SHARE MODE का उपयोग करता है और ऑटोकॉमिट अक्षम है? मुझे पता है कई (सबसे / सभी?) डेटाबेस सर्वर अब सही क्रमांकन के बजाय डिफ़ॉल्ट रूप से स्नैपशॉट अलगाव का उपयोग करते हैं, लेकिन धारावाहिक पठनीयता को मजबूर करने के लिए अभी भी सामयिक औचित्य नहीं हैं? लेकिन ऐसा लगता है कि आप कह रहे थे कि सभी सामान्य मामलों में, MySQL में डिफ़ॉल्ट स्थितियाँ ऐसे रीड लॉक का कारण नहीं बनती हैं जो अन्य थ्रेड्स को प्रभावित करते हैं, इसलिए एक समस्या के बारे में चिंता न करें जो आपके पास नहीं है? मैंने अपने पतन, बीटीडब्ल्यू को पूर्ववत करने की कोशिश की। क्षमा करें ...
क्रेग

3
मैंने कहा "सामान्य रूप से नहीं"। मेरा मतलब था कि यदि आप एक सामान्य चयन करते हैं (बिना अपडेट या लॉक इन शेयर मोड के लिए) और डिफ़ॉल्ट लेनदेन अलगाव स्तर का उपयोग करें। अलगाव स्तर को बदलने के लिए कुछ वैध मामले हैं, लेकिन मैं इसे केवल प्रति-सत्र के आधार पर करूँगा जो कभी भी डिफ़ॉल्ट नहीं होता है।
10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.