सबसे छोटे के लिए लेन-देन अलगाव स्तर



आज मैं एक अत्यंत दिलचस्प लाना चाहूंगा, लेकिन अक्सर डेटाबेस के साधारण नश्वर प्रोग्रामर अनुभाग (डीबी) के लिए रहस्यों के साथ कवर किया जाता है - लेनदेन पृथक स्तर। जैसा कि अभ्यास से पता चलता है, आईटी से जुड़े कई लोग, विशेष रूप से डेटाबेस के साथ काम करने में, इन स्तरों की आवश्यकता क्यों होती है और उन्हें अपने लाभ के लिए कैसे उपयोग किया जा सकता है, इसकी बहुत कम समझ है।

सिद्धांत की बिट


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

पर्यावरण की तैयारी


उदाहरण के लिए, MySQL DBMS को चुना गया था। PostgreSQL का उपयोग भी किया जा सकता है, लेकिन यह रीड अनक्मिटेड आइसोलेशन स्तर का समर्थन नहीं करता है, और इसके बजाय रीड कमिटेड स्तर का उपयोग करता है। और जैसा कि यह निकला, अलग-अलग डीबीएमएस अलग-अलग स्तर का अनुभव करते हैं। अलगाव सुनिश्चित करने में उनकी विभिन्न बारीकियां हो सकती हैं, अतिरिक्त स्तर हो सकते हैं या अच्छी तरह से ज्ञात नहीं हैं।

डॉकर हब के साथ समाप्त MySQL छवि का उपयोग करके एक वातावरण बनाएं। और डेटाबेस भरें।

डोकर-compose.yaml
version: '3.4' services: db: image: mysql:8 environment: - MYSQL_ROOT_PASSWORD=12345 command: --init-file /init.sql volumes: - data:/var/lib/mysql - ./init.sql:/init.sql expose: - "3306" ports: - "3309:3306" volumes: data: 


डेटाबेस को आबाद करना
 create database if not exists bank; use bank; create table if not exists accounts ( id int unsigned auto_increment primary key, login varchar(255) not null, balance bigint default 0 not null, created_at timestamp default now() ) collate=utf8mb4_unicode_ci; insert into accounts (login, balance) values ('petya', 1000); insert into accounts (login, balance) values ('vasya', 2000); insert into accounts (login, balance) values ('mark', 500); 


आइए विचार करें कि स्तर कैसे काम करते हैं और उनकी विशेषताएं क्या हैं।
हम एक साथ निष्पादित लेनदेन पर 2 पर उदाहरण निष्पादित करेंगे। सशर्त रूप से, बाएं विंडो में लेन-देन को लेनदेन 1 (T1) कहा जाएगा, दाएं विंडो में - लेनदेन 2 (T2)।

बिना पढ़े लिखे


सबसे खराब डेटा स्थिरता के साथ स्तर, लेकिन उच्चतम लेनदेन की गति। स्तर का नाम खुद के लिए बोलता है - प्रत्येक लेनदेन एक और लेनदेन में गंदे बदलाव ( गंदे पढ़ने की घटना) को देखता है। आइए देखें कि इस तरह के लेनदेन एक दूसरे को कैसे प्रभावित करते हैं।

चरण 1. हम 2 समानांतर लेनदेन शुरू करते हैं।



चरण 2. हम देखते हैं कि हमारे पास शुरुआत में क्या जानकारी है।



चरण 3. अब हम टी 1 में INSERT, DELETE, UPDATE संचालन करते हैं, और देखते हैं कि अब कोई अन्य लेनदेन क्या देखता है।



T2 एक अन्य लेनदेन के डेटा को देखता है जो अभी तक प्रतिबद्ध नहीं है।

चरण 4. और टी 2 कुछ डेटा प्राप्त कर सकते हैं।



चरण 5. जब आप वापस T1 में परिवर्तन करते हैं, तो T2 द्वारा प्राप्त डेटा त्रुटिपूर्ण होगा।



इस स्तर पर, डेटा का उपयोग करना असंभव है, जिसके आधार पर आवेदन के लिए महत्वपूर्ण निष्कर्ष और महत्वपूर्ण निर्णय किए जाते हैं क्योंकि ये निष्कर्ष वास्तविकता से बहुत दूर हो सकते हैं।
इस स्तर का उपयोग किया जा सकता है, उदाहरण के लिए, किसी चीज़ की अनुमानित गणना के लिए। परिणाम COUNT (*) या MAX (*) का उपयोग कुछ गैर-सख्त रिपोर्टों में किया जा सकता है।
एक अन्य उदाहरण डिबग मोड है। लेन-देन के दौरान, आप देखना चाहते हैं कि डेटाबेस में क्या होता है।

प्रतिबद्ध पढ़ो


इस स्तर के लिए, समवर्ती निष्पादित लेनदेन अन्य लेनदेन से केवल प्रतिबद्ध परिवर्तन देखते हैं। इस प्रकार, यह स्तर गंदे पढ़ने से सुरक्षा प्रदान करता है।

चरण 1 और चरण 2 पिछले उदाहरण के समान हैं।

चरण 3. हम खाते तालिका (टी 1) के साथ 3 सरल ऑपरेशन भी करते हैं और दोनों लेनदेन में इन तालिकाओं का पूर्ण चयन करते हैं।



और हम देखेंगे कि गंदे पढ़ने की घटना टी 2 में अनुपस्थित है।

चरण 4. हम टी 1 में बदलावों को ठीक करते हैं और जांचते हैं कि टी 2 अब क्या देखता है।



अब टी 2 वह सब कुछ देखता है जो टी 1 ने किया है। जब हम अद्यतन और हटाई गई लाइनें (UPDATE, DELETE) देखते हैं, और जब हम जोड़ा रिकॉर्ड (INSERT) देखते हैं, तो पढ़ने की घटना को गैर - दोहराई जाने वाली तथाकथित घटना है।

बार-बार पढ़ने योग्य


गैर-दोहराने की घटना को रोकने के लिए एक स्तर। यानी हम किसी अन्य लेन-देन के साथ किसी अन्य लेनदेन में परिवर्तित और हटाए गए रिकॉर्ड नहीं देखते हैं। लेकिन हम अभी भी किसी अन्य लेनदेन से सम्मिलित रिकॉर्ड देखते हैं। पढ़ना प्रेत कहीं भी नहीं जाता है।

चरण 1 और चरण 2 को फिर से दोहराएं।

चरण 3. T1 में, हम INSERT, UPDATE और DELETE क्वेरी को निष्पादित करते हैं। T2 के बाद, हम उसी लाइन को अपडेट करने की कोशिश करते हैं जो T1 में अपडेट की गई थी।



और हमें लॉक मिलता है: टी 2 तब तक इंतजार करेगा जब तक टी 1 परिवर्तन या रोल वापस नहीं लेता।

चरण 4. T1 द्वारा किए गए परिवर्तनों को ठीक करें। और टी 2 में अकाउंट टेबल से फिर से डेटा पढ़ें।



जैसा कि आप देख सकते हैं, गैर-दोहराव पढ़ने और प्रेत के पढ़ने की घटनाएं नहीं देखी जाती हैं। यह कैसे होता है, डिफ़ॉल्ट रूप से, दोहराने योग्य पढ़ने से हम केवल गैर-दोहराए गए पढ़ने की घटना को रोक सकते हैं?

वास्तव में, MySQL में दोहराने योग्य पढ़ने के स्तर के लिए प्रेत पढ़ने के प्रभाव का अभाव है। और PostgreSQL में, उन्होंने इस स्तर के लिए भी छुटकारा पा लिया। हालांकि इस स्तर के शास्त्रीय प्रतिनिधित्व में, हमें इस आशय का पालन करना चाहिए।

एक छोटा सार उदाहरण उपहार प्रमाण पत्र (कोड) और उनके उपयोग को उत्पन्न करने की सेवा है। उदाहरण के लिए, एक हमलावर ने खुद के लिए एक प्रमाण पत्र कोड तैयार किया और इसे सक्रिय करने की कोशिश करता है, एक कूपन को सक्रिय करने के लिए एक पंक्ति में कई अनुरोध भेजने की कोशिश करता है। इस मामले में, हम एक ही कूपन के साथ काम करते हुए कई समवर्ती निष्पादित लेनदेन शुरू करेंगे। और कुछ स्थितियों में, कूपन का डबल या यहां तक ​​कि ट्रिपल सक्रियण हो सकता है (उपयोगकर्ता को 2x / 3x बोनस प्राप्त होगा)। दोहराने योग्य पढ़ने के साथ , इस मामले में, एक लॉक होगा और सक्रियण एक बार होगा, और पिछले 2 स्तरों में, एकाधिक सक्रियण संभव है। इसी तरह की समस्या को SELECT FOR UPDATE क्वेरी का उपयोग करके भी हल किया जा सकता है, जो अद्यतन रिकॉर्ड (कूपन) को भी अवरुद्ध करेगा।

serializable


जिस स्तर पर लेनदेन व्यवहार करते हैं जैसे कि कुछ और मौजूद नहीं है, एक दूसरे पर कोई प्रभाव नहीं है। शास्त्रीय प्रतिनिधित्व में, यह स्तर पढ़ने के प्रभाव को समाप्त करता है।

चरण 1. लेनदेन शुरू करें।

चरण 2. टी 2 हम खाते तालिका पढ़ते हैं, फिर टी 1 हम टी 2 द्वारा पढ़े गए डेटा को अपडेट करने का प्रयास करते हैं।



हमें लॉक मिलता है: हम डेटा को दूसरे में पढ़े गए ट्रांजेक्शन में नहीं बदल सकते।

चरण 3. INSERT और DELETE दोनों ही हमें T1 में लॉक तक ले जाते हैं।



जब तक टी 2 अपना काम पूरा नहीं करता, तब तक हम उस डेटा के साथ काम नहीं कर पाएंगे जो उसने पढ़ा है। हमें अधिकतम डेटा संगति मिलती है, कोई अतिरिक्त डेटा रिकॉर्ड नहीं किया जाएगा। इसके लिए कीमत लगातार ताले के कारण धीमी लेनदेन की गति है, इसलिए एक खराब एप्लिकेशन आर्किटेक्चर के साथ यह आप पर एक चाल खेल सकता है।

निष्कर्ष


अधिकांश अनुप्रयोगों में, अलगाव स्तर शायद ही कभी बदलता है और डिफ़ॉल्ट मान का उपयोग किया जाता है (उदाहरण के लिए, MySQL में यह दोहराए जाने योग्य पढ़ा जाता है , PostgreSQL में यह प्रतिबद्ध है )।

लेकिन समय-समय पर ऐसी समस्याएं होती हैं जिनमें उच्च डेटा स्थिरता या लेन-देन की गति के बीच एक बेहतर संतुलन ढूंढना कुछ एप्लिकेशन समस्या को हल करने में मदद कर सकता है।

Source: https://habr.com/ru/post/hi469415/


All Articles