Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

FK के साथ पंक्ति अद्यतन करते समय MySQL का प्रदर्शन

निम्नलिखित स्कीमा पर विचार करें:(आपकी सुविधा के लिए शेष बचे हैं) :

-- drop table if exists spies;
create table spies
(   id int primary key,
    weapon_id int not null,
    name varchar(100) not null,
    key(weapon_id),
    foreign key (weapon_id) references weapons(id)
)engine=InnoDB;

-- drop table if exists weapons;
create table weapons
(   id int primary key,
    name varchar(100) not null
)engine=InnoDB;

insert weapons(id,name) values (1,'slingshot'),(2,'Ruger');
insert spies(id,weapon_id,name) values (1,2,'Sally');
-- truncate table spies;

अब, हमारे पास 2 प्रक्रियाएँ हैं, P1 और P2। यह परीक्षण करने के लिए सबसे अच्छा है कि P1 शायद MySQL कार्यक्षेत्र कहाँ है और P2 एक MySql कमांड-लाइन विंडो है। दूसरे शब्दों में, आपको इसे अलग कनेक्शन और अधिकार के रूप में सेट करना होगा। आपको इन्हें उचित तरीके से चरण-दर-चरण चलाने के लिए सावधानीपूर्वक नजर रखनी होगी (कथा में वर्णित) नीचे) और अन्य प्रक्रिया विंडो पर इसके प्रभाव को देखें।

निम्नलिखित प्रश्नों पर विचार करें, यह ध्यान में रखते हुए कि एक स्पष्ट लेनदेन में लपेटा नहीं गया एक MySQL क्वेरी स्वयं एक अंतर्निहित लेनदेन है। लेकिन नीचे, मैं स्पष्ट शब्दों के लिए आया:

Q1:

START TRANSACTION;
-- place1
UPDATE spies SET name = 'Bond', weapon_id = 1 WHERE id = 1;
-- place2
COMMIT;

Q2:

START TRANSACTION;
-- place1
UPDATE spies SET name = 'Bond' WHERE id = 1;
-- place2
COMMIT;

Q3:

START TRANSACTION;
-- place1
SELECT id into @mine_to_use from weapons where id=1 FOR UPDATE; -- place2
-- place3
COMMIT;

Q4:

START TRANSACTION;
-- place1
SELECT id into @mine_to_use from spies where id=1 FOR UPDATE; -- place2
-- place3
COMMIT;

Q5 (प्रश्नों का हॉज पोज):

SELECT * from weapons;
SELECT * from spies;

कथा

Q1: जब P1 प्रारंभ होता है Q1 , और स्थान 2 पर पहुंच जाता है, इसने आईडी =1 पंक्ति (प्रत्येक तालिका में कुल 2 पंक्तियाँ, 1 पंक्ति) के लिए हथियारों और जासूसों दोनों तालिकाओं में एक विशेष पंक्ति-स्तरीय अपडेट लॉक प्राप्त किया है। यह साबित किया जा सकता है कि P2 Q3 को चलाना शुरू कर देता है, स्थान 1 पर पहुंच जाता है, लेकिन स्थान 2 पर अवरुद्ध हो जाता है, और केवल तभी मुक्त हो जाता है जब P1 COMMIT को कॉल करने के लिए इधर-उधर हो जाता है। P2 रनिंग Q3 के बारे में मैंने अभी जो कुछ कहा है, वह P2 रनिंग Q4 के लिए ठीक वैसा ही है। संक्षेप में, P2 स्क्रीन पर, P1 कमिट होने तक प्लेस2 फ़्रीज हो जाता है।

निहित लेनदेन के बारे में फिर से एक नोट। आपका असली Q1 क्वेरी इसे बहुत तेज़ी से निष्पादित करने जा रही है और इससे बाहर आने से एक अंतर्निहित प्रतिबद्धता होगी। हालाँकि, यदि आप अधिक समय-महंगे दिनचर्या चलाने वाले थे, तो पूर्व पैराग्राफ इसे तोड़ देता है।

Q2: जब P1 प्रारंभ होता है Q2 , और स्थान 2 पर पहुंच जाता है, इसने आईडी =1 पंक्ति (प्रत्येक तालिका में कुल 2 पंक्तियाँ, 1 पंक्ति) के लिए हथियारों और जासूसों दोनों तालिकाओं में एक विशेष पंक्ति-स्तरीय अपडेट लॉक प्राप्त किया है। हालांकि, P2 में Q3 को weapons को ब्लॉक करने में कोई समस्या नहीं है , लेकिन P2 में Q4 चल रहे स्थान2 spies . पर ब्लॉक समस्याएँ हैं ।

इसलिए, Q1 और Q2 के बीच का अंतर यह जानते हुए MySQL पर आ जाता है कि FK इंडेक्स UPDATE के कॉलम के लिए प्रासंगिक नहीं है, और मैनुअल में कहा गया है कि Note1 में नीचे।

जब P1 Q1 चलाता है, P2 को केवल-पढ़ने के लिए गैर-लॉक Q5 प्रकार के प्रश्नों को प्राप्त करने में कोई समस्या नहीं है। केवल समस्या यह है कि डेटा प्रस्तुतिकरण P2 को मौजूद ISOLATION LEVEL के आधार पर क्या दिखाई देता है।

नोट1 :MySQL मैनुअल पेज से जिसका शीर्षक है अलग द्वारा लॉक सेट InnoDB में SQL कथन :

यही कारण है कि Q2: . का व्यवहार ऐसा है कि P2 एक अद्यतन करने के लिए स्वतंत्र है या weapons पर एक अद्यतन अनन्य क्षणिक लॉक प्राप्त कर सकता है . इसका कारण यह है कि इंजन हथियार_आईडी पर P1 के साथ अद्यतन प्रदर्शन नहीं कर रहा है और इस प्रकार उस तालिका में पंक्ति-स्तरीय लॉक नहीं है।

इसे 50,000 फीट तक वापस खींचने के लिए, किसी की सबसे बड़ी चिंता वह अवधि है जिस पर या तो एक अंतर्निहित लेनदेन (जिसमें कोई START/COMMIT नहीं है), या एक COMMIT से पहले स्पष्ट लेनदेन है। एक सहकर्मी प्रक्रिया को अनिश्चित काल के लिए सिद्धांत रूप में अद्यतन की आवश्यकता प्राप्त करने से प्रतिबंधित किया जा सकता है। लेकिन उस लॉक को प्राप्त करने का प्रत्येक प्रयास innodb_lock_wait_timeout . इसका मतलब है, डिफ़ॉल्ट रूप से, लगभग 60 सेकंड के बाद यह समय समाप्त हो जाता है। अपनी सेटिंग देखने के लिए, दौड़ें:

select @@innodb_lock_wait_timeout;

मेरे लिए, फिलहाल, यह 50 (सेकंड) है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. jOOQ के साथ अंतराल के साथ date_sub () फ़ंक्शन को कार्यान्वित करना

  2. मेरा MySQL सर्वर कौन सा संस्करण है?

  3. धाराप्रवाह निबर्ननेट:MySQL से डेटाबेस कनेक्शन नहीं बना सकता

  4. असीमित डायनामिक फ़ील्ड के लिए मेरे MySQL डेटाबेस डिज़ाइन की आलोचना करें

  5. क्या कई विदेशी कुंजी समझ में आती हैं?