InterSystems IRIS жаһандық жүйесіндегі транзакциялар

InterSystems IRIS жаһандық жүйесіндегі транзакцияларInterSystems IRIS ДҚБЖ деректерді сақтауға арналған қызықты құрылымдарды қолдайды - ғаламдық. Негізінде, бұл транзакциялар түріндегі әртүрлі қосымша жақсылықтары бар көп деңгейлі кілттер, деректер ағаштарын өтуге арналған жылдам функциялар, құлыптар және өзінің ObjectScript тілі.

Ғаламшарлар туралы толығырақ «Глобалдар деректерді сақтауға арналған қазына-семсер» мақалалар сериясынан оқыңыз:

Ағаштар. 1 бөлім
Ағаштар. 2 бөлім
Сирек массивтер. 3-бөлім

Мені транзакциялардың жаһандық елдерде қалай жүзеге асырылатыны, қандай мүмкіндіктер бар екендігі қызықтырды. Өйткені, бұл әдеттегі кестелерге қарағанда деректерді сақтауға арналған мүлдем басқа құрылым. Әлдеқайда төмен деңгей.

Реляциялық мәліметтер базасының теориясынан белгілі болғандай, транзакциялардың жақсы орындалуы талаптарды қанағаттандыруы керек ACID:

A - атомдық (атомдық). Мәміледе енгізілген барлық өзгерістер немесе мүлде жоқ.

C - жүйелілік. Транзакция аяқталғаннан кейін дерекқордың логикалық күйі ішкі сәйкес болуы керек. Көп жағдайда бұл талап бағдарламашыға қатысты, бірақ SQL дерекқорлары жағдайында ол сыртқы кілттерге де қатысты.

Мен - оқшаулау. Параллель орындалатын транзакциялар бір-біріне әсер етпеуі керек.

D - Төзімді. Транзакция сәтті аяқталғаннан кейін төменгі деңгейлердегі мәселелер (мысалы, электр қуатының үзілуі) транзакция арқылы өзгертілген деректерге әсер етпеуі керек.

Глобалдар реляциялық емес деректер құрылымдары болып табылады. Олар өте шектеулі жабдықта өте жылдам жұмыс істеуге арналған. пайдалану арқылы жаһандық транзакцияларды жүзеге асыруды қарастырайық IRIS докерінің ресми кескіні.

IRIS жүйесінде транзакцияларды қолдау үшін келесі пәрмендер пайдаланылады: TSTART, TCOMMIT, ТРОЛБЕК.

1. Атомдық

Тексерудің ең оңай жолы - атомдық. Біз дерекқор консолінен тексереміз.

Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMIT

Содан кейін біз қорытынды жасаймыз:

Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)

Біз алып жатырмыз:

1 2 3

Бәрі жақсы. Атомдық сақталады: барлық өзгерістер жазылады.

Тапсырманы қиындатып, қатені енгізіп, транзакцияның жартылай немесе мүлде сақталмағанын көрейік.

Атомдылықты қайтадан тексерейік:

Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3

Содан кейін біз контейнерді күшпен тоқтатып, оны іске қосып, көреміз.

docker kill my-iris

Бұл пәрмен дерлік мәжбүрлеп өшіруге тең, себебі ол процесті дереу тоқтату үшін SIGKILL сигналын жібереді.

Мүмкін транзакция ішінара сақталған шығар?

WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)

– Жоқ, ол аман қалған жоқ.

Қайтару пәрменін қолданып көрейік:

Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TROLLBACK

WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)

Ештеңе де аман қалған жоқ.

2. Жүйелілік

Глобалдарға негізделген дерекқорларда кілттер глобальдерде де жасалғандықтан (жаһандық реляциялық кестеге қарағанда деректерді сақтауға арналған төменгі деңгейлі құрылым екенін еске саламын), сәйкестік талабын қанағаттандыру үшін кілттің өзгеруін қосу керек. жаһандық өзгеріс сияқты транзакцияда.

Мысалы, бізде жеке тұлғаларды сақтайтын жаһандық ^адам бар және біз кілт ретінде СТН пайдаланамыз.

^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...

Тегі мен аты бойынша жылдам іздеу үшін біз ^ индекс кілтін жасадық.

^index(‘Kamenev’, ‘Sergey’, 1234567) = 1

Деректер базасы дәйекті болуы үшін біз келесідей тұлғаны қосуымыз керек:

TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMIT

Тиісінше, жою кезінде біз транзакцияны да пайдалануымыз керек:

TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMIT

Басқаша айтқанда, жүйелілік талабын орындау толығымен бағдарламашының иығына жүктеледі. Бірақ жаһандық деңгейге келетін болсақ, бұл олардың төмен деңгейіне байланысты қалыпты жағдай.

3. Оқшаулау

Жабайы табиғат осы жерден басталады. Көптеген пайдаланушылар бір уақытта бір дерекқорда жұмыс істейді, сол деректерді өзгертеді.

Жағдай көптеген пайдаланушылар бір уақытта бір код репозиторийімен жұмыс істеген кезде және бір уақытта көптеген файлдарға өзгертулер енгізуге тырысқан кездегі жағдаймен салыстыруға болады.

Деректер базасы барлығын нақты уақытта сұрыптауы керек. Маңызды компанияларда нұсқаларды басқаруға (филиалдарды біріктіруге, қақтығыстарды шешуге және т.б.) жауап беретін арнайы адам бар екенін және деректер базасы мұның барлығын нақты уақыт режимінде, тапсырманың күрделілігін және дұрыс орындалу дұрыстығын ескерсек. деректер базасының дизайны және оған қызмет көрсететін код.

Деректер базасы пайдаланушылар бір деректерде жұмыс істеп жатқан жағдайда, қақтығыстарды болдырмау үшін орындайтын әрекеттердің мағынасын түсіне алмайды. Ол басқасына қайшы келетін бір транзакцияны ғана қайтара алады немесе оларды ретімен орындай алады.

Тағы бір мәселе, транзакцияны орындау кезінде (міндеттемеге дейін) деректер қорының күйі сәйкес келмеуі мүмкін, сондықтан басқа транзакциялар реляциялық деректер қорларында қол жеткізілетін деректер қорының сәйкессіз күйіне қол жеткізе алмайтыны жөн. көптеген жолдармен: суретті жасау, көп нұсқалы жолдар және т.б.

Транзакцияларды параллель орындаған кезде біз үшін олардың бір-біріне кедергі жасамауы маңызды. Бұл оқшаулау қасиеті.

SQL 4 оқшаулау деңгейін анықтайды:

  • БІРІКПЕЙ ОҚЫҢЫЗ
  • ОҚЫЛДЫ
  • Қайталанатын ОҚУ
  • СЕРИЯЛЫҚ

Әр деңгейді бөлек қарастырайық. Әрбір деңгейді іске асыру шығындары экспоненциалды түрде өседі.

БІРІКПЕЙ ОҚЫҢЫЗ - бұл оқшаулаудың ең төменгі деңгейі, бірақ сонымен бірге ең жылдам. Транзакциялар бір-бірімен жасалған өзгерістерді оқи алады.

ОҚЫЛДЫ оқшаулаудың келесі деңгейі болып табылады, бұл ымыраға келу. Транзакциялар міндеттемеге дейін бір-бірінің өзгертулерін оқи алмайды, бірақ олар міндеттемеден кейін жасалған кез келген өзгертулерді оқи алады.

Егер бізде T1 сияқты деректермен жұмыс істеген T2, T3 ... Tn транзакцияларында міндеттемелер орын алған ұзақ транзакция T1 болса, онда T1 деректерін сұраған кезде біз әр жолы әртүрлі нәтиже аламыз. Бұл құбылыс қайталанбайтын оқу деп аталады.

Қайталанатын ОҚУ — бұл оқшаулау деңгейінде бізде қайталанбайтын оқу құбылысы жоқ, себебі деректерді оқуға әрбір сұраныс үшін нәтиже деректерінің суреті жасалады және сол транзакцияда қайта пайдаланылған кезде суреттен алынған деректер пайдаланылады. Дегенмен, бұл оқшаулау деңгейінде фантомдық деректерді оқуға болады. Бұл параллель орындалған транзакциялар арқылы қосылған жаңа жолдарды оқуға қатысты.

СЕРИЯЛЫҚ — оқшаулаудың ең жоғары деңгейі. Ол транзакцияда (оқу немесе өзгерту) кез келген тәсілмен пайдаланылған деректер бірінші транзакция аяқталғаннан кейін ғана басқа транзакциялар үшін қолжетімді болуымен сипатталады.

Алдымен транзакциядағы операцияларды негізгі ағыннан оқшаулау бар-жоғын анықтап алайық. 2 терминал терезесін ашайық.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

Ешқандай оқшаулау жоқ. Бір жіп транзакцияны ашқан екіншісі не істеп жатқанын көреді.

Әртүрлі ағындардың транзакциялары олардың ішінде не болып жатқанын көретінін көрейік.

2 терминал терезесін ашып, 2 транзакцияны қатар ашайық.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

Параллель транзакциялар бір-бірінің деректерін көреді. Сонымен, біз ең қарапайым, бірақ сонымен бірге ең жылдам оқшаулау деңгейін алдық, READ UNCOMMITED.

Негізінде, бұл өнімділік әрқашан басымдыққа ие болған жаһандық елдер үшін күтуге болады.

Егер жаһандық операцияларда оқшаулаудың жоғары деңгейі қажет болса ше?

Мұнда сіз оқшаулау деңгейлері не үшін қажет және олар қалай жұмыс істейтіні туралы ойлануыңыз керек.

Оқшауланудың ең жоғары деңгейі, SERIALIZE, параллель орындалған транзакциялар нәтижесі соқтығыстардың болмауына кепілдік беретін олардың дәйекті орындалуына баламалы екенін білдіреді.

Біз мұны ObjectScript-тегі смарт құлыптар арқылы жасай аламыз, олардың әртүрлі қолданылуы бар: пәрмен арқылы тұрақты, қосымша, бірнеше құлыптауды орындауға болады. LOCK.

Төменгі оқшаулау деңгейлері дерекқор жылдамдығын арттыруға арналған келіссөздер болып табылады.

Құлыптардың көмегімен оқшаулаудың әртүрлі деңгейлеріне қалай қол жеткізуге болатынын көрейік.

Бұл оператор деректерді өзгерту үшін қажет эксклюзивті құлыптарды ғана емес, сонымен қатар оқу процесі кезінде басқа процестермен өзгертілмейтін деректерді оқу қажет болған кезде бірнеше ағындарды қатар қабылдай алатын ортақ құлыптарды алуға мүмкіндік береді.

Екі фазалы блоктау әдісі туралы қосымша ақпарат орыс және ағылшын тілдерінде:

Екі фазалы блоктау
Екі фазалы құлыптау

Қиындығы транзакция кезінде деректер қорының күйі сәйкес келмеуі мүмкін, бірақ бұл сәйкес келмейтін деректер басқа процестерге көрінеді. Мұны қалай болдырмауға болады?

Құлыптарды пайдалана отырып, біз дерекқордың күйі сәйкес болатын көріну терезелерін жасаймыз. Және келісілген күйдің мұндай көріну терезелеріне барлық қол жеткізу құлыптармен басқарылатын болады.

Бір деректердегі ортақ құлыптарды қайта пайдалануға болады — бірнеше процесс оларды қабылдауы мүмкін. Бұл құлыптар басқа процестердің деректерді өзгертуіне жол бермейді, яғни. олар дәйекті дерекқор күйінің терезелерін қалыптастыру үшін пайдаланылады.

Деректерді өзгерту үшін эксклюзивті құлыптар қолданылады - мұндай құлыпты тек бір процесс қабылдай алады. Эксклюзивті құлыпты келесі жолдармен алуға болады:

  1. Деректер тегін болса, кез келген процесс
  2. Тек осы деректерде ортақ құлпы бар және эксклюзивті құлыптауды бірінші болып сұраған процесс.

InterSystems IRIS жаһандық жүйесіндегі транзакциялар

Көріну терезесі неғұрлым тар болса, соғұрлым басқа процестер оны күтеді, бірақ оның ішіндегі дерекқордың күйі соғұрлым дәйекті болуы мүмкін.

READ_COMMITTED — бұл деңгейдің мәні мынада: біз тек басқа ағындардан жасалған деректерді көреміз. Егер басқа транзакциядағы деректер әлі жасалмаса, біз оның ескі нұсқасын көреміз.

Бұл құлыптың босатылуын күтудің орнына жұмысты параллельдеуге мүмкіндік береді.

Арнайы трюктарсыз біз IRIS-те деректердің ескі нұсқасын көре алмаймыз, сондықтан құлыптармен айналысуға тура келеді.

Тиісінше, деректерді тек дәйектілік сәтінде оқуға мүмкіндік беру үшін ортақ құлыптарды пайдалануға тура келеді.

Бізде бір-біріне ақша аударатын пайдаланушы базасы бар делік.

123-ші тұлғадан 242-ші тұлғаға ауысу сәті:

LOCK +^person(123), +^person(242)
Set ^person(123, amount) = ^person(123, amount) - amount
Set ^person(242, amount) = ^person(242, amount) + amount
LOCK -^person(123), -^person(242)

123-адамнан ақша сомасын дебеттеу алдында сұрау сәті эксклюзивті блокпен (әдепкі бойынша):

LOCK +^person(123)
Write ^person(123)

Жеке кабинетте тіркелгі күйін көрсету қажет болса, сіз ортақ құлыпты пайдалана аласыз немесе оны мүлде қолданбайсыз:

LOCK +^person(123)#”S”
Write ^person(123)

Дегенмен, егер дерекқор операциялары дерлік орындалады деп болжасақ (глобалдар реляциялық кестеге қарағанда әлдеқайда төмен деңгейлі құрылым екенін еске саламын), онда бұл деңгейге қажеттілік төмендейді.

Қайталанатын ОҚУ - Бұл оқшаулау деңгейі бір уақыттағы транзакциялар арқылы өзгертуге болатын деректерді бірнеше рет оқуға мүмкіндік береді.

Тиісінше, біз өзгертетін деректерді оқуға ортақ құлыпты және біз өзгертетін деректерге эксклюзивті құлыптарды қоюымыз керек.

Бақытымызға орай, LOCK операторы бір мәлімдемеде көп болуы мүмкін барлық қажетті құлыптарды егжей-тегжейлі тізімдеуге мүмкіндік береді.

LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)

басқа операциялар (қазіргі уақытта параллель ағындар ^person(123, сома) өзгертуге тырысады, бірақ мүмкін емес)

LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)

чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”

Үтірмен бөлінген құлыптарды тізімдеу кезінде олар дәйекті түрде қабылданады, бірақ мұны істесеңіз:

LOCK +(^person(123),^person(242))

содан кейін олар бірден атомдық түрде алынады.

СЕРИЯЛАНДЫРУ — жалпы деректері бар барлық транзакциялар дәйекті түрде орындалатындай етіп құлыптарды орнатуымыз керек. Бұл тәсіл үшін құлыптардың көпшілігі эксклюзивті болуы керек және өнімділік үшін ғаламдық аймақтың ең кішкентай аймақтарында қабылдануы керек.

Егер жаһандық ^ тұлғадағы қаражатты дебеттеу туралы айтатын болсақ, онда ол үшін тек SERIALIZE оқшаулау деңгейі қолайлы, өйткені ақшаны қатаң дәйектілікпен жұмсау керек, әйтпесе бірдей соманы бірнеше рет жұмсауға болады.

4. Төзімділік

Мен контейнерді қатты кесу арқылы сынақтар өткіздім

docker kill my-iris

База оларға жақсы шыдады. Ешқандай проблема анықталмады.

қорытынды

Ғаламдық елдер үшін InterSystems IRIS транзакцияға қолдау көрсетеді. Олар шын мәнінде атомдық және сенімді. Жаһандық өлшемдерге негізделген дерекқордың үйлесімділігін қамтамасыз ету үшін бағдарламашы күш-жігері және транзакцияларды пайдалану қажет, өйткені оның сыртқы кілттер сияқты күрделі кіріктірілген құрылымдары жоқ.

Құлыптарды қолданбай глобальдердің оқшаулану деңгейі READ UNCOMMITED болып табылады және құлыптарды пайдаланған кезде оны SERIALIZE деңгейіне дейін қамтамасыз етуге болады.

Жаһандық транзакциялардың дұрыстығы мен жылдамдығы бағдарламалаушының шеберлігіне байланысты: оқу кезінде ортақ құлыптар неғұрлым кеңірек пайдаланылса, оқшаулау деңгейі соғұрлым жоғары болады және неғұрлым тар эксклюзивті құлыптар қабылданса, өнімділік соғұрлым жылдамырақ болады.

Ақпарат көзі: www.habr.com

пікір қалдыру