{"id":36650,"date":"2019-10-31T22:12:54","date_gmt":"2019-10-31T19:12:54","guid":{"rendered":"https:\/\/prohoster.info\/blog\/tranzaktsii-v-globalah-intersystems-iris\/"},"modified":"2019-10-31T22:12:54","modified_gmt":"2019-10-31T19:12:54","slug":"tranzaktsii-v-globalah-intersystems-iris","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","title":{"rendered":"Transakcje w globalach InterSystems IRIS","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Transakcje w globalach InterSystems IRIS\" src=\"\/wp-content\/uploads\/2019\/07\/ee4e58369616511dc213f94158b04e4f.jpg\" style=\"display:block;margin: 0 auto;\" \/>Baza danych InterSystems IRIS obs\u0142uguje interesuj\u0105ce struktury do przechowywania danych \u2013 globalne. W zasadzie s\u0105 to wielopoziomowe klucze z r\u00f3\u017cnymi dodatkowymi funkcjonalno\u015bciami, takimi jak transakcje, szybkie funkcje do przeszukiwania drzew danych, blokady oraz w\u0142asny j\u0119zyk ObjectScript.<\/p>\n<p>Wi\u0119cej o globalnych w cyklu artyku\u0142\u00f3w \u201eGlobalne \u2013 miecze-klucze do przechowywania danych\u201d:<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/263791\/\">Drzewa. Cz\u0119\u015b\u0107 1<\/a><\/noindex> <br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/264173\/\">Drzewa. Cz\u0119\u015b\u0107 2<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/268465\/\">Rzadkie macierze. Cz\u0119\u015b\u0107 3<\/a><\/noindex><\/p>\n<p>Zaciekawi\u0142o mnie, jak realizowane s\u0105 transakcje w globalnych, jakie tam s\u0105 szczeg\u00f3lne cechy. Poniewa\u017c jest to zupe\u0142nie inna struktura do przechowywania danych ni\u017c wszystkim znane tabele. O wiele bardziej niskopoziomowe.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nJak wiadomo z teorii relacyjnych baz danych, dobra realizacja transakcji powinna spe\u0142nia\u0107 wymagania <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">ACID<\/a><\/noindex>:<\/p>\n<p><b>A \u2014 Atomic (atomowo\u015b\u0107).<\/b> Rejestrowane s\u0105 wszystkie zmiany dokonane w transakcji lub nie ma \u017cadnych.<\/p>\n<p><b>S \u2014 Consistency (sp\u00f3jno\u015b\u0107).<\/b> Po zako\u0144czeniu transakcji logiczny stan bazy danych powinien by\u0107 wewn\u0119trznie sp\u00f3jny. W du\u017cej mierze to wymaganie dotyczy programisty, ale w przypadku baz danych SQL dotyczy tak\u017ce kluczy obcych.<\/p>\n<p><b>I \u2014 Isolate (izolacja).<\/b> R\u00f3wnolegle wykonywane transakcje nie powinny wp\u0142ywa\u0107 na siebie nawzajem.<\/p>\n<p><b>D \u2014 Durable (trwa\u0142o\u015b\u0107).<\/b> Po pomy\u015blnym zako\u0144czeniu transakcji problemy na ni\u017cszych poziomach (przyk\u0142ad: awaria zasilania) nie powinny wp\u0142ywa\u0107 na dane zmienione przez transakcj\u0119.<\/p>\n<p>Globalne to struktury danych nierelacyjne. Zosta\u0142y stworzone do ultra szybkiej pracy na bardzo ograniczonym sprz\u0119cie. Przyjrzyjmy si\u0119 wdro\u017ceniu transakcji w globalnych przy u\u017cyciu <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/_\/intersystems-iris-data-platform\/plans\/222f869e-567c-4928-b572-eb6a29706fbd?tab=instructions\">oficjalnego obrazu dockerowego IRIS<\/a><\/noindex>.<\/p>\n<p>Aby wspiera\u0107 transakcje w IRIS u\u017cywa si\u0119 polece\u0144: <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctstart\">TSTART<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctcommit\">TCOMMIT<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctrollback\">TROLLBACK<\/a><\/noindex>.<\/p>\n<h2>1. Atomowo\u015b\u0107<\/h2>\n<p>\nNaj\u0142atwiej jest sprawdzi\u0107 atomowo\u015b\u0107. Sprawdzamy z konsoli bazy danych.<\/p>\n<pre><code class=\"bash\">Kill ^a\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3\nTCOMMIT<\/code><\/pre>\n<p>\nNast\u0119pnie dokonujemy odczytu:<\/p>\n<pre><code class=\"bash\">Write ^a(1), \u201c \u201d, ^a(2), \u201c \u201d, ^a(3)<\/code><\/pre>\n<p>\nOtrzymamy:<\/p>\n<pre><code class=\"bash\">1 2 3<\/code><\/pre>\n<p>\nWszystko w porz\u0105dku. Atomowo\u015b\u0107 przestrzegana: wszystkie zmiany zosta\u0142y zapisane.<\/p>\n<p>Utrudnimy zadanie, wprowadzimy b\u0142\u0105d i zobaczymy, jak zachowa si\u0119 transakcja, cz\u0119\u015bciowo lub wcale.<\/p>\n<p>Jeszcze raz sprawdzimy atomowo\u015b\u0107:<\/p>\n<pre><code class=\"bash\">Kill ^A\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3<\/code><\/pre>\n<p>\nPo czym przymusowo zatrzymamy kontener, uruchomimy go i sprawdzimy. <\/p>\n<pre><code class=\"bash\">docker kill my-iris<\/code><\/pre>\n<p>\nTo polecenie jest praktycznie r\u00f3wnowa\u017cne z nag\u0142ym odci\u0119ciem zasilania, poniewa\u017c wysy\u0142a sygna\u0142 natychmiastowego zatrzymania procesu SIGKILL.<\/p>\n<p>Czy transakcja mog\u0142a si\u0119 zapisa\u0107 cz\u0119\u015bciowo?<\/p>\n<pre><code class=\"bash\">WRITE ^a(1), ^a(2), ^a(3)\n^\n ^a(1)<\/code><\/pre>\n<p>\n \u2014 Nie, nie zosta\u0142a zapisana.<\/p>\n<p>Wypr\u00f3bujmy polecenie wycofania:<\/p>\n<pre><code class=\"bash\">Kill ^A\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3\nTROLLBACK\n\nWRITE ^a(1), ^a(2), ^a(3)\n^\n ^a(1)<\/code><\/pre>\n<p>\nTe\u017c nic nie zosta\u0142o zapisane.<\/p>\n<h2>2. Sp\u00f3jno\u015b\u0107<\/h2>\n<p>\nPoniewa\u017c w bazach na globalach klucze s\u0105 r\u00f3wnie\u017c tworzone na globalach (przypomn\u0119, \u017ce global to struktura o ni\u017cszym poziomie do przechowywania danych ni\u017c tabela relacyjna), aby spe\u0142ni\u0107 wym\u00f3g sp\u00f3jno\u015bci, nale\u017cy zmiany klucza uwzgl\u0119dni\u0107 w tej samej transakcji, co zmiana globalu.<\/p>\n<p>Na przyk\u0142ad mamy global ^person, w kt\u00f3rym przechowujemy persony i jako klucz u\u017cywamy NIP.<\/p>\n<pre><code class=\"bash\">^person(1234567, 'firstname') = 'Sergey'\n^person(1234567, 'lastname') = 'Kamenev'\n^person(1234567, 'phone') = '+74995555555\n...<\/code><\/pre>\n<p>\nAby mie\u0107 szybkie wyszukiwanie wed\u0142ug nazwiska i imienia, stworzyli\u015bmy klucz ^index.<\/p>\n<pre><code class=\"bash\">^index('Kamenev', 'Sergey', 1234567) = 1<\/code><\/pre>\n<p>\nAby baza by\u0142a sp\u00f3jna, musimy dodawa\u0107 person\u0119 w ten spos\u00f3b:<\/p>\n<pre><code class=\"bash\">TSTART\n^person(1234567, 'firstname') = 'Sergey'\n^person(1234567, 'lastname') = 'Kamenev'\n^person(1234567, 'phone') = '+74995555555\n^index('Kamenev', 'Sergey', 1234567) = 1\nTCOMMIT<\/code><\/pre>\n<p>\nOdpowiednio, przy usuwaniu r\u00f3wnie\u017c musimy u\u017cywa\u0107 transakcji:<\/p>\n<pre><code class=\"bash\">TSTART\nKill ^person(1234567)\nZKill ^index('Kamenev', 'Sergey', 1234567)\nTCOMMIT<\/code><\/pre>\n<p>\nInnymi s\u0142owy, realizacja wymogu sp\u00f3jno\u015bci le\u017cy ca\u0142kowicie w gestii programisty. Ale kiedy mowa o globalach \u2014 jest to normalne, z uwagi na ich niskopoziomow\u0105 natur\u0119.<\/p>\n<h2>3. Izolacja<\/h2>\n<p>\nTutaj zaczynaj\u0105 si\u0119 zawirowania. Wiele u\u017cytkownik\u00f3w jednocze\u015bnie pracuje nad t\u0105 sam\u0105 baz\u0105, zmieniaj\u0105c te same dane.<\/p>\n<p>Sytuacja jest por\u00f3wnywalna z tym, kiedy wielu u\u017cytkownik\u00f3w jednocze\u015bnie pracuje z tym samym repozytorium kodu i pr\u00f3buje jednocze\u015bnie zatwierdzi\u0107 zmiany w wielu plikach.<\/p>\n<p>Baza danych musi to wszystko rozwi\u0105zywa\u0107 w czasie rzeczywistym. Bior\u0105c pod uwag\u0119, \u017ce w powa\u017cnych firmach jest nawet specjalna osoba odpowiedzialna za kontrol\u0119 wersji (za \u0142\u0105czenie ga\u0142\u0119zi, rozwi\u0105zywanie konflikt\u00f3w itp.), a DB musi to wszystko robi\u0107 w czasie rzeczywistym, staje si\u0119 oczywista z\u0142o\u017cono\u015b\u0107 zadania oraz poprawno\u015b\u0107 projektowania bazy danych i kodu, kt\u00f3ry j\u0105 obs\u0142uguje.<\/p>\n<p>Baza danych nie mo\u017ce zrozumie\u0107 intencji dzia\u0142a\u0144 podejmowanych przez u\u017cytkownik\u00f3w, aby unikn\u0105\u0107 konflikt\u00f3w, gdy pracuj\u0105 nad tymi samymi danymi. Mo\u017ce jedynie cofn\u0105\u0107 jedn\u0105 transakcj\u0119, kt\u00f3ra jest sprzeczna z inn\u0105 lub wykona\u0107 je sekwencyjnie.<\/p>\n<p>Innym problemem jest to, \u017ce podczas realizacji transakcji (przed zatwierdzeniem), stan bazy danych mo\u017ce by\u0107 niesp\u00f3jny, dlatego po\u017c\u0105dane jest, aby inne transakcje nie mia\u0142y dost\u0119pu do niesp\u00f3jnego stanu bazy danych, co osi\u0105ga si\u0119 w relacyjnych bazach danych na wiele sposob\u00f3w: poprzez tworzenie migawk\u00f3w, wersjonowanie wierszy itp.<\/p>\n<p>Podczas r\u00f3wnoleg\u0142ego wykonywania transakcji wa\u017cne jest, aby nie przeszkadza\u0142y sobie nawzajem. To jest w\u0142a\u015bnie w\u0142a\u015bciwo\u015b\u0107 izolacji.<\/p>\n<p>SQL definiuje 4 poziomy izolacji:<\/p>\n<ul>\n<li>ODCZYT NIEZAJ\u0118TY<\/li>\n<li>ODCZYT ZA\u0141ATWIONY<\/li>\n<li>POWTARZALNY ODCZYT<\/li>\n<li>SERIALIZOWANY<\/li>\n<\/ul>\n<p>\nRozwa\u017cmy ka\u017cdy poziom oddzielnie. Koszty wdro\u017cenia ka\u017cdego poziomu rosn\u0105 prawie wyk\u0142adniczo.<\/p>\n<p><b>ODCZYT NIEZAJ\u0118TY<\/b> \u2014 to najni\u017cszy poziom izolacji, ale jednocze\u015bnie najszybszy. Transakcje mog\u0105 odczytywa\u0107 zmiany wprowadzone przez siebie nawzajem.<\/p>\n<p><b>ODCZYT ZA\u0141ATWIONY<\/b> \u2014 to nast\u0119pny poziom izolacji, kt\u00f3ry jest kompromisem. Transakcje nie mog\u0105 odczytywa\u0107 zmian wprowadzonych przez siebie nawzajem do momentu zatwierdzenia, ale mog\u0105 odczytywa\u0107 wszelkie zmiany wprowadzone po zatwierdzeniu.<\/p>\n<p>Je\u015bli mamy d\u0142ug\u0105 transakcj\u0119 T1, w trakcie kt\u00f3rej mia\u0142y miejsce zatwierdzenia w transakcjach T2, T3... Tn, kt\u00f3re pracowa\u0142y z tymi samymi danymi co T1, to przy zapytaniu o dane w T1 b\u0119dziemy za ka\u017cdym razem otrzymywa\u0107 r\u00f3\u017cny wynik. Zjawisko to nazywa si\u0119 niepowtarzalnym odczytem.<\/p>\n<p><b>POWTARZALNY ODCZYT<\/b> \u2014 na tym poziomie izolacji nie wyst\u0119puje zjawisko niepowtarzalnego odczytu, poniewa\u017c dla ka\u017cdego zapytania o odczyt danych tworzona jest migawka danych wyniku, a przy ponownym wykorzystaniu w tej samej transakcji wykorzystywane s\u0105 dane z migawki. Jednak w tym poziomie izolacji mo\u017cliwe jest odczytywanie danych fantomowych. Mamy na my\u015bli odczyt nowych wierszy, kt\u00f3re zosta\u0142y dodane przez r\u00f3wnoleg\u0142e zatwierdzone transakcje.<\/p>\n<p><b>SERIALIZOWANY<\/b> \u2014 najwy\u017cszy poziom izolacji. Charakteryzuje si\u0119 tym, \u017ce dane w jakikolwiek spos\u00f3b wykorzystywane w transakcji (odczyt lub zmiana) staj\u0105 si\u0119 dost\u0119pne dla innych transakcji dopiero po zako\u0144czeniu pierwszej transakcji.<\/p>\n<p>Na pocz\u0105tek sprawd\u017amy, czy operacje w transakcji s\u0105 izolowane od g\u0142\u00f3wnego w\u0105tku. Otw\u00f3rzmy 2 okna terminala.<\/p>\n<pre><code class=\"bash\">Kill ^t\n\nWrite ^t(1)\n2<\/code><\/pre>\n<pre><code class=\"bash\">\nTSTART\nSet ^t(1)=2<\/code><\/pre>\n<p>\nNie ma izolacji. Jeden w\u0105tek widzi, co robi drugi, kt\u00f3ry otworzy\u0142 transakcj\u0119.<\/p>\n<p>Zobaczmy, czy transakcje r\u00f3\u017cnych w\u0105tk\u00f3w widz\u0105 to, co dzieje si\u0119 wewn\u0105trz nich. <\/p>\n<p>Otw\u00f3rzmy 2 okna terminala i uruchommy 2 transakcje r\u00f3wnolegle.<\/p>\n<pre><code class=\"bash\">kill ^t\nTSTART\nWrite ^t(1)\n3<\/code><\/pre>\n<pre><code class=\"bash\">\nTSTART\nSet ^t(1)=3\n<\/code><\/pre>\n<p>\nR\u00f3wnolegle wykonywane transakcje widz\u0105 dane nawzajem. Zatem otrzymali\u015bmy najprostszy, ale i najszybszy poziom izolacji READ UNCOMMITTED.<\/p>\n<p>W zasadzie mo\u017cna by\u0142o si\u0119 tego spodziewa\u0107 dla global\u00f3w, dla kt\u00f3rych wydajno\u015b\u0107 zawsze by\u0142a najwa\u017cniejsza. <\/p>\n<p>Co zrobi\u0107, je\u015bli b\u0119dziemy potrzebowa\u0107 wy\u017cszego poziomu izolacji w operacjach na globalach?<\/p>\n<p>Trzeba zastanowi\u0107 si\u0119, po co w og\u00f3le potrzebne s\u0105 poziomy izolacji i jak dzia\u0142aj\u0105.<\/p>\n<p>Najwy\u017cszy poziom izolacji SERIALIZE oznacza, \u017ce wyniki r\u00f3wnolegle wykonywanych transakcji s\u0105 r\u00f3wnowa\u017cne ich sekwencyjnemu wykonaniu, co gwarantuje brak kolizji.<\/p>\n<p>Mo\u017cemy to osi\u0105gn\u0105\u0107 za pomoc\u0105 odpowiednich blokad w ObjectScript, kt\u00f3re maj\u0105 wiele r\u00f3\u017cnych sposob\u00f3w zastosowania: mo\u017cna stosowa\u0107 blokady zwyk\u0142e, inkrementacyjne lub wielokrotne polecenia. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/latest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_clock\">LOCK<\/a><\/noindex>.<\/p>\n<p>Ni\u017csze poziomy izolacji to kompromisy maj\u0105ce na celu zwi\u0119kszenie szybko\u015bci dzia\u0142ania bazy danych.<\/p>\n<p>Zobaczmy, jak mo\u017cemy osi\u0105gn\u0105\u0107 r\u00f3\u017cne poziomy izolacji za pomoc\u0105 blokad.<\/p>\n<p>Ten operator pozwala na uzyskiwanie nie tylko ekskluzywnych blokad, potrzebnych do modyfikacji danych, ale tak\u017ce tzw. shared, kt\u00f3re mog\u0105 by\u0107 zajmowane r\u00f3wnolegle przez wiele w\u0105tk\u00f3w, gdy musz\u0105 odczyta\u0107 dane, kt\u00f3re nie powinny by\u0107 zmienione przez inne procesy podczas odczytu.<\/p>\n<p>Wi\u0119cej informacji o dwufazowej metodzie blokad w j\u0119zyku polskim i angielskim:<\/p>\n<p>\u2192 <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%94%D0%B2%D1%83%D1%85%D1%84%D0%B0%D0%B7%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0\">Dwufazowa blokada<\/a><\/noindex><br \/>\n\u2192 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_locking\">Two-phase locking<\/a><\/noindex><\/p>\n<p>Trudno\u015b\u0107 polega na tym, \u017ce w trakcie transakcji stan bazy mo\u017ce by\u0107 niesp\u00f3jny, jednak te niesp\u00f3jne dane s\u0105 widoczne dla innych proces\u00f3w. Jak tego unikn\u0105\u0107?<\/p>\n<p>Stworzymy za pomoc\u0105 blokad takie okna widoczno\u015bci, w kt\u00f3rych stan bazy b\u0119dzie sp\u00f3jny. Wszelkie dost\u0119py do takich okien widoczno\u015bci sp\u00f3jnego stanu b\u0119d\u0105 kontrolowane przez blokady.<\/p>\n<p>Blokady wsp\u00f3\u0142dzielone tych samych danych s\u0105 wielokrotne \u2014 mog\u0105 by\u0107 u\u017cywane przez kilka proces\u00f3w. Blokady te zabraniaj\u0105 innym procesom zmiany danych, tzn. s\u0105 wykorzystywane do formowania okien sp\u00f3jnego stanu bazy danych.<\/p>\n<p>Blokady ekskluzywne s\u0105 u\u017cywane do zmiany danych \u2014 tak\u0105 blokad\u0119 mo\u017ce przej\u0105\u0107 tylko jeden proces. Blokad\u0119 ekskluzywn\u0105 mo\u017ce przej\u0105\u0107:<\/p>\n<ol>\n<li>Ka\u017cdy proces, je\u015bli dane s\u0105 wolne.<\/li>\n<li>Tylko ten proces, kt\u00f3ry ma na te dane blokad\u0119 wsp\u00f3\u0142dzielon\u0105 i jako pierwszy za\u017c\u0105da\u0142 blokady ekskluzywnej.<\/li>\n<\/ol>\n<p>\n<img decoding=\"async\" alt=\"Transakcje w globalach InterSystems IRIS\" src=\"\/wp-content\/uploads\/2019\/07\/bb91ed1268925bc1b9266763ab82646a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIm w\u0119\u017csze okno widoczno\u015bci, tym d\u0142u\u017cej musz\u0105 czeka\u0107 inne procesy, ale tym sp\u00f3jniejszy mo\u017ce by\u0107 stan bazy danych w nim.<\/p>\n<p><b>READ_COMMITED<\/b> \u2014 sednem tego poziomu jest to, \u017ce widzimy tylko zatwierdzone dane z innych w\u0105tk\u00f3w. Je\u015bli dane w innej transakcji nie zosta\u0142y jeszcze zatwierdzone, widzimy ich star\u0105 wersj\u0119.<\/p>\n<p>Pozwala nam to na r\u00f3wnoleg\u0142e dzia\u0142anie zamiast czekania na zwolnienie blokady.<\/p>\n<p>Bez specjalnych sztuczek nie b\u0119dziemy mogli zobaczy\u0107 starej wersji danych w IRIS, dlatego b\u0119dziemy musieli ograniczy\u0107 si\u0119 do blokad.<\/p>\n<p>Odpowiednio musimy za pomoc\u0105 blokad wsp\u00f3\u0142dzielonych zezwoli\u0107 na odczyt danych tylko w momentach sp\u00f3jno\u015bci.<\/p>\n<p>Za\u0142\u00f3\u017cmy, \u017ce mamy baz\u0119 u\u017cytkownik\u00f3w ^person, kt\u00f3rzy przelewaj\u0105 sobie nawzajem pieni\u0105dze.<\/p>\n<p>Moment przelewu od osoby 123 do osoby 242:<\/p>\n<pre><code class=\"bash\">LOCK +^person(123), +^person(242)\nSet ^person(123, amount) = ^person(123, amount) - amount\nSet ^person(242, amount) = ^person(242, amount) + amount\nLOCK -^person(123), -^person(242)<\/code><\/pre>\n<p>\nMoment zapytania o kwot\u0119 pieni\u0119dzy u osoby 123 przed obci\u0105\u017ceniem musi by\u0107 poprzedzony blokad\u0105 ekskluzywn\u0105 (domy\u015blnie):<\/p>\n<pre><code class=\"bash\">LOCK +^person(123)\nWrite ^person(123)<\/code><\/pre>\n<p>\nA je\u015bli trzeba pokaza\u0107 stan konta w panelu u\u017cytkownika, to mo\u017cna u\u017cy\u0107 blokady wsp\u00f3\u0142dzielonej lub w og\u00f3le jej nie u\u017cywa\u0107:<\/p>\n<pre><code class=\"bash\">LOCK +^person(123)#\u201dS\u201d\nWrite ^person(123)<\/code><\/pre>\n<p>\nJednak je\u015bli za\u0142o\u017cymy, \u017ce operacje na bazie danych s\u0105 wykonywane praktycznie natychmiast (przypominam, \u017ce globalne zmienne s\u0105 znacznie bardziej niskopoziomow\u0105 struktur\u0105 ni\u017c tabela relacyjna), to potrzeba tego poziomu spada.<\/p>\n<p><b>POWTARZALNY ODCZYT<\/b> \u2014 na tym poziomie izolacji dopuszczalne jest, \u017ce mog\u0105 wyst\u0105pi\u0107 kilka odczyt\u00f3w danych, kt\u00f3re mog\u0105 by\u0107 zmieniane przez r\u00f3wnoleg\u0142e transakcje. <\/p>\n<p>Odpowiednio musimy ustawi\u0107 blokad\u0119 wsp\u00f3\u0142dzielon\u0105 na odczyt danych, kt\u00f3re zmieniamy oraz blokady ekskluzywne na dane, kt\u00f3re zmieniamy.<\/p>\n<p>Operator LOCK allows you to detail all necessary locks in one operator, which can be quite numerous.<\/p>\n<pre><code class=\"bash\">LOCK +^person(123, amount)#\u201dS\u201d\nreading ^person(123, amount)<\/code><\/pre>\n<p>\nother operations (during this time, parallel threads attempt to modify ^person(123, amount), but cannot)<\/p>\n<pre><code class=\"bash\">LOCK +^person(123, amount)\nmodification ^person(123, amount)\nLOCK -^person(123, amount)\n\nreading ^person(123, amount)\nLOCK -^person(123, amount)#\u201dS\u201d<\/code><\/pre>\n<p>\nWhen listing locks separated by commas, they are acquired sequentially, but if done this way:<\/p>\n<pre><code class=\"bash\">LOCK +(^person(123),^person(242))<\/code><\/pre>\n<p>\nthey are taken atomically all at once.<\/p>\n<p><b>SERIALIZE<\/b> \u2014 we need to set locks in such a way that ultimately all transactions that share data are executed sequentially. For this approach, most locks must be exclusive and obtained over the smallest areas of the global for performance.<\/p>\n<p>If we talk about spending money in global ^person, only SERIALIZE isolation level is acceptable, as money must be spent strictly sequentially, otherwise it is possible to spend the same amount multiple times.<\/p>\n<h2>4. Durability<\/h2>\n<p>\nI conducted tests with hard container shutdowns using<\/p>\n<pre><code class=\"bash\">docker kill my-iris<\/code><\/pre>\n<p>\nThe database handled it well. No problems were identified.<\/p>\n<h2>Podsumowanie<\/h2>\n<p>\nFor globals in InterSystems IRIS, there is support for transactions. They are indeed atomic and reliable. To ensure database consistency for globals, programmer effort and transaction usage are necessary, as there are no complex built-in constructs like foreign keys.<\/p>\n<p>The isolation level for globals without the use of locks is READ UNCOMMITTED, and with locks, it can be ensured up to the SERIALIZE level.<\/p>\n<p>The correctness and speed of transaction execution on globals heavily depend on the programmer's skill: the more widely shared locks are used when reading, the higher the isolation level, and the more narrowly exclusive locks are taken, the greater the performance.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/461753\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044b. \u041f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u043b\u044e\u0448\u043a\u0430\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439, \u0431\u044b\u0441\u0442\u0440\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u0434\u0435\u0440\u0435\u0432\u044c\u0435\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 ObjectScript. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 \u0432 \u0446\u0438\u043a\u043b\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u00ab\u0413\u043b\u043e\u0431\u0430\u043b\u044b \u2014 \u043c\u0435\u0447\u0438-\u043a\u043b\u0430\u0434\u0435\u043d\u0446\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\u00bb: \u0414\u0435\u0440\u0435\u0432\u044c\u044f. \u0427\u0430\u0441\u0442\u044c 1 \u0414\u0435\u0440\u0435\u0432\u044c\u044f. \u0427\u0430\u0441\u0442\u044c 2 \u0420\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b. \u0427\u0430\u0441\u0442\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27448,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36650","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 InterSystems IRIS | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:12:54+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:12:54+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Transactions in globals InterSystems IRIS | ProHoster","description":"The InterSystems IRIS DBMS supports interesting structures.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 InterSystems IRIS | ProHoster","og:description":"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:12:54+00:00","article:modified_time":"2019-10-31T19:12:54+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36650","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:17:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:41:52","updated":"2026-01-22 04:17:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/36650","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=36650"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/36650\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/27448"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=36650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=36650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=36650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}