Funkcjonalność BLF

03 listopad 2011, ratajczykl

Telefony VoIP oferują coraz większe możliwości usług dodanych do obsługi połączeń telefonicznych. Wartą uwagi jest funkcjonalność BLF, ang. Busy Lamp Field. Funkcja ta jest często wykorzystywana:

  • w urządzeniach posiadających kilka linii rozróżnianych za pomocą podświetlonego przycisku,
  • w telefonach z przystawkami sekretarskimi.

Za pośrednictwem BLF, centrala PBX (Asterisk) informuje danego użytkownika telefonii VoIP na bieżąco o statusie innego użytkownika - od rozpoczęcia wywoływania połączenia, przez odebranie i ostatecznie rozłączenie.

Przykład konfiguracji przedstawiony jest na podstawie centralki PBX Asterisk oraz telefonu IP Yealink T-38G – posiada on dwukolorowe diody przy przyciskach oraz możliwość podpięcia przystawki sekretarskiej.

Możemy rozróżnić następujące stany monitorowanego połączenia:

  • Ringing (dioda miga na czerwono) - rozpoczęcie wywoływania użytkownika.
  • Connected/Busy (dioda świeci na czerwono) –użytkownik prowadzi rozmowę.
  • Idle (dioda świeci na zielono) – użytkownik gotowy do odebrania połączenia (BLF nie informują np. o DND)

Podstawową konfigurację można oprzeć na: http://www.freeconet.pl/pl/pomoc/instrukcja-asterisk rozszerzając ją o dodatkowe konta użytkowników tak, aby zaprezentować pełnię możliwości .

Istotne w konfiguracji Asteriska są parametry:

call-limit=100
limitonpeer=yes
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
SIP.conf

[code]
[general]

context=default - Wszystkie nieznane połączenia kierowane są do kontekstu default extensions.conf
bindport=5172 - Zwykle atakujący szukają Asterisk-ów na domyślnym porcie sip, czyli 5060. Warto ustawić inny np. 5172 Uwaga! w konfiguracji telefonów trzeba będzie wpisać ten port jako port proxy zamiast 5060
srvlookup=yes - Dla zwiększenia redundancji należy włączyć rozwiązywanie domeny po rekordach SRV (w przypadku problemów z dodzwonieniem konieczne jest ustawienie wartości „no”)
defaultexpiry=60 - Przydatne przy Asteriskach na niepublicznych adresach IP (za NATem)
allowguest=no - Zabezpiecza przed nieautoryzowanymi wywołaniami (domyślnie Asterisk zezwala na takie wywołania)
dtmfmode = rfc2833 - ustawiania dla FreecoNet
nat=yes - ustawienia dla bramek/telefonów za NATem
localnet=192.168.2.0/255.255.255.0 - adres i maska sieci lokalnej
;externip=123.234.123.234 - adres publiczny routera, za którym jest Asterisk
register => ***:***@sip.freeconet.pl/przychodzace1 - konto:haslo@domena/kontekst(?)

sip.conf

[freeconet-out]

type=peer - do operatora
username=*** - nazwa konta we FreecoNet
secret=*** - SIP (terminala) konta FreecoNet
fromdomain=sip.freeconet.pl
context=FreecoNet - informacja, na jaki kontekst w extensions.conf maja przychodzić połączenia

host=sip.freeconet.pl
port=5060
outboundproxy=sip.freeconet.pl
outboundproxyport=5060
insecure=no

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[freeconet-in1] podobnie dwa peery dla połączeń przychodzących

type=peer
fromdomain=sip.freeconet.pl
port=5060
context=freeconet
host=213.218.116.65
insecure=no

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[freeconet-in2]

type=peer
fromdomain=sip.freeconet.pl
port=5060
context=freeconet
host=213.218.116.66
insecure=no

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[telefon1] przykład konfiguracji telefonu

context=tel1 - informacje, o kontekście przetwarzania
type=friend - jest użytkownikiem
username=telefon1 - nazwa użytkownika
secret=telefon1 - hasło, którym użytkownik uwierzytelnia się
callerid=”Kowalski Jan” <100> - id - tekst oraz numer
host=dynamic - może być gdziekolwiek w sieci
nat=yes - również na NATem
accountcode=Kowalscy - Kowalscy - dodatkowe dla billingów wewnętrznych Asteriska
allow=All - kodeki (tu wszystkie)

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[telefon2] przykład konfiguracji telefonu

context=tel2 - informacje, o kontekście przetwarzania
type=friend - jest użytkownikiem
username=telefon2 - nazwa użytkownika
secret=telefon2- hasło, którym użytkownik uwierzytelnia się
callerid=”Piotr Nowak” <101> - id - tekst oraz numer
host=dynamic - może być gdziekolwiek w sieci
nat=yes - również na NATem
accountcode=Kowalscy - Kowalscy - dodatkowe dla billingów wewnętrznych Asteriska
allow=All - kodeki (tu wszystkie)

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[telefon3] przykład konfiguracji telefonu

context=tel3 - informacje, o kontekście przetwarzania
type=friend - jest użytkownikiem
username=telefon3 - nazwa użytkownika
secret=telefon3- hasło, którym użytkownik uwierzytelnia się
callerid=”Anna Lewandowska” <102> - id - tekst oraz numer
host=dynamic - może być gdziekolwiek w sieci
nat=yes - również na NATem
accountcode=Kowalscy - Kowalscy - dodatkowe dla billingów wewnętrznych Asteriska
allow=All - kodeki (tu wszystkie)

call-limit=100 - zezwolenie na więcej wejść do extension
limitonpeer=yes - aby BLF działały zgodnie z oczekiwaniami
notifyringing=yes
notifyhold=yes
allowsubscribe=yes
- zezwolenie na subscribe’y - na nich opiera się działanie BLF

[/code]

extensions.conf

[code]

[default] - niebezpieczny kontekst dla nieproszonych gości
exten => _X.,1,Hangup - bez szans na wykonanie połączenia
[freeconet] - kontekst docelowy peerów FreecoNet

exten => przychodzace1,1,Set(TOHDR=${SIP_HEADER(To)})

exten => przychodzace1,2,GotoIf($["${REGEX("611234567" ${TOHDR})}" = "1"]?wew,100,1)

exten => przychodzace1,3,GotoIf($["${REGEX("611234568" ${TOHDR})}" = "1"]?wew,101,1)

exten => przychodzace1,4,GotoIf($["${REGEX("611234569" ${TOHDR})}" = "1"]?wew,102,1)

[tel1]

exten => t,1,Hangup

exten => h,1,Hangup

include => wew

exten => _XXX.,1,SIPAddHeader(X-Fid: ${SIPCALLID}) - opcjonalne to, co stanie w miejscu ${SIPCALLID} pojawi się w billingach csv w panelu FreecoNet
exten => _XXX.,2,Set(CALLERID(num)=48611234569) - ustawienie publicznego numeru telefonu (w panelu trzeba ustawić prezentację “użyj z bramki”)
exten => _XXX.,3,Dial(SIP/${EXTEN}@freeconet-out) - resztą połączenia zajmiemy się my!

exten => 100,hint,SIP/telefon1 - instrukcje odpowiedzialne za BLF, umieszczenie w kontekście danego użytkownika lub w [default], jeśli pozwolimy każdemu na sprawdzanie statusów
exten => 101,hint,SIP/telefon2
exten => 102,hint,SIP/telefon3

exten => 900,hint,SIP/freeconet-in2&SIP/freeconet-in1&SIP/freeconet-out - za pomocą & można połączyć kilka peerów do jednego subscribe’a;
exten składa się z: exten => (nazwa lub numer który wpisujemy w telefonie VOIP w polu value),(hint),SIP/(nazwa peera)

[tel2]

include => wew

exten => t,1,Hangup

exten => h,1,Hangup

exten => _XXX.,1,SIPAddHeader(X-Fid: ${SIPCALLID}) - opcjonalne to, co stanie w miejscu ${SIPCALLID} pojawi się w billingach csv w panelu FreecoNet
exten => _XXX.,2,Set(CALLERID(num)=48611234568) - ustawienie publicznego numeru telefonu (w panelu trzeba ustawić prezentację “użyj z bramki”)
exten => _XXX.,3,Dial(SIP/${EXTEN}@freeconet-out) - resztą połączenia zajmiemy się my!

[tel3]

include => wew
exten => t,1,Hangup
exten => h,1,Hangup

exten => _XXX.,1,SIPAddHeader(X-Fid: ${SIPCALLID}) - opcjonalne to, co stanie w miejscu ${SIPCALLID} pojawi się w billingach csv w panelu FreecoNet
exten => _XXX.,2,Set(CALLERID(num)=48611234567) - ustawienie publicznego numeru telefonu (w panelu trzeba ustawić prezentację “użyj z bramki”)
exten => _XXX.,3,Dial(SIP/${EXTEN}@freeconet-out) - resztą połączenia zajmiemy się my!

exten => 100,hint,SIP/telefon1

exten => 101,hint,SIP/telefon2

exten => 102,hint,SIP/telefon3

exten => 900,hint,SIP/freeconet-in2&SIP/freeconet-in1&SIP/freeconet-out

[wew]

exten => 100,1,Dial(SIP/telefon1,45,Tt)

exten => 101,1,Dial(SIP/telefon2,45,Tt)

exten => 102,1,Dial(SIP/telefon3,45,Tt)

[/code]

(Jeśli chcemy zablokować możliwość sprawdzania statusów użytkowników wystarczy dodać allowsubscribe=no w [general] w sip.conf )

W telefonie VoIP wpisujemy w polu value numer, który mamy w exten => 102,hint,SIP/telefon3 , a extension to numer, na który zadzwonimy po naciśnięciu przycisku.

Warto zapoznać się również z http://www.voip-info.org/wiki/view/Asterisk+standard+extensions

Muzyczne upodobania VoIP’a

28 wrzesień 2011, ratajczykl

Wszyscy wiemy o tym, że były prowadzone liczne badania na temat wpływu muzyki na wzrost roślin czy na wielkość dziennego udoju. Nikt jednak nie badał czy bezduszne systemy informatyczne i telekomunikacyjne mogą mieć jakieś muzyczne upodobania.

Nie pierwszy raz Aiton Caldwell wyprzedza wszystkich:) Jak to zwykle bywa z „odkryciami” – o większości z nich decyduje przypadek (kto pamięta o tym, że wynalazca penicyliny ubił bakterie przez zwyczajną niechlujność?), przejdźmy jednak do meritum.

Przy jakościowych testach połączeń przez jednego z naszych operatorów, znudzeni ciągłą wymianą liczebników miedzy uczestnikami testu (a próbowaliśmy je wymieniać stosując różne ciągi, w tym Fibbonacci’ego), postanowiliśmy zastąpić usta testera głośnikiem. Dzwoniliśmy z platformy przez testowanego operatora do sieci stacjonarnej PSTN, gdzie stał owy głośnik i nadawał. Nie mieliśmy jednak pod ręką nagranych kolejnych liczebników, posłużyliśmy się więc kilkoma utworami znanych wykonawców.

Testy dały wynik, który zaskoczył nas całkowicie. Nie każdą bowiem muzykę system operatora był w stanie znieść. Można by tu sporządzić cały ranking utworów, do których system miał wstręt, lecz na potrzebę tego tekstu podam pojedynczy przykład. Dokładnie w chwili 1:04 odtwarzania “Message in a Bottle” Stinga, system operatora miał dość i rozłączał połączenie. Powtarzalne w stu procentach! Minuta i cztery sekundy – koniec połączenia.

No i bylibyśmy pewnie juz pod opieką ludzi w białych kitlach, gdyby nie krótkie oględziny sygnalizacji przychodzącej od operatora. Operator ten interpretuje specyficzne dźwięki muzyki jako sygnał faksu i próbuje zmienić protokół na t.38, co nie podoba się zwykłemu telefonowi IP.

A może warto zostawić technikę i zrobić ranking anty-przebojów gateway’a operatora? Może jednak system “telco” ma duszę…?

[MZm]

Prezentacja Datery na 3camp

07 styczeń 2011, Michał Szymański

Prawdopodobnie pod koniec stycznia połączone siły Datera S.A i Freeconet S.A  wystąpią z prezentacją na spotkaniach 3camp w Gdańsku. Tematem wystąpienia będzie przedstawienie historii z wdrożenia rozwiązań Business Intelligence firmy Jaspersoft w Freeconet S.A. Dokładny termin wykładu jest jeszcze nie znany ale z całą pewnością poinformujemy o tym w kolejnym wpisie.

Nowa wersja FreecoNet API URL 3.05

24 listopad 2010, admin

W dniu dzisiejszym została wdrożona nowa wersja API wersja 3.05. W tej wersji została dodana funkcjonalność pozwalająca funkcji getBilling zwracać kolumnę callId.  Kolumna callId jest unikalnym identyfikatorem pozwalający powiązać ze sobą kilka przekierowanych połączeń.

Nowsze wrogiem dobrego..

28 sierpień 2010, Michał Szymański

Przeczytałem artykuł Enterprise OSGi i po raz kolejny naszła mnie pewna refleksja. Lubię Jave z tego też powodu używamy jej w wielu projektach w naszej firmie, jednak mam wrażenie, że świat Javy ma tendencje do komplikowania spraw raczej prostych. Z tego, co wiem, OSGi wymaga czasu, żeby być fachowcem w tym framework’u i jeśli rozwiązanie jest przełomowe, ponieważ rozwiązuje problem wprowadzony przez niedopracowaną koncepcję manifestów, to według mnie to jest coś nie tak (oczywiście dość mocno upraszczam przełomowość OSGi, ale robię to celowo). To raczej ciało standaryzacji Javy powinno zastanowić się, co z tym tematem zrobić i to sam język ‘jakoś’ powinien ten problem rozwiązać. Koncepcji nie można nazywać ‘przełomową’ tylko z tego powodu, że  naprawia sztuczne problemy wprowadzone przez sam język.

Drugie wrażenie jest takie, że producenci systemów wspomagających tworzenie oprogramowania dla Javy skupiają się na pogoni za implementacją nowych standardów kosztem stabilności wytworzonych rozwiązań. W przypadku np. baz danych naprawdę ciężko znaleźć błędy w wersjach stabilnych. Mogę podać jako potwierdzenie tezy przykład z naszego ‘podwórka’. Używamy bazę Postgres od 4 lat i jak na razie znaleźliśmy jeden mały błąd. Natomiast w przypadku produktu JBoss (to jest tylko przykład) już na etapie testów rozwiązania znaleźliśmy poważne błędy.

Trzecie wrażenie jest takie, że Javowcy mają tendencje do przekomplikowanych rozwiązań, argumentem za wprowadzaniem takich rozwiązań jest to, że owszem jest to skomplikowane, ale później będzie łatwe w utrzymaniu, z tym że za 2-3lata okazuje się, że zastosowane rozwiązania są już ‘nie trendy’ i lepiej stosować coś nowszego = przepisujemy na nowe technologie.

Może trochę przesadzam w swoich opiniach jednak według mnie środowisko Javy powinno zastanowić się nad wspomnianymi przeze mnie wnioskami, może rezultaty ‘zadumy’, w jakim kierunku zmierza świat Javy, poprawiłoby zdanie o tym języku  wielu zatwardziałych przeciwników.

Jak zwiększyć efektywność pracy

19 czerwiec 2010, admin

Po wielu latach bezowocnych prób z różnymi metodykami wytwarzania oprogramowania obiecujących  zwiększenie  efektywności pracy programistów wydaje, się w końcu znalazłem coś  co wyprowadzi każdy projekt informatyczny z problemów związanych z ograniczonymi możliwościami człowieka.   Razor Venom bo o tym rewolucyjnym produkcie mowa może nie jest tani jednak reklama przekonała mnie, że naprawdę warto zainwestować paręset dolarów. Zresztą zobaczcie  sami o czym mówię - RAZOR VENOM.

Konferencja ICIT’2010

18 czerwiec 2010, Maciej Krajewski

W dniach 28-30 czerwca na Politechnice Gdańskiej odbędzie się II międzynarodowa konferencja odnośnie technologii informacyjnej ICIT’2010 wraz z VIII Krajową Konferencją Technologie Informacyjne IT’2010. W ramach konferencji, razem z kolegami z DATERY Sebastianem Zaprzalskim, Michał Pietrasiakiem oraz Krzysztofem Raszkowskim  przedstawimy trzy prezentację dotyczące tematyki VoIP:

  • BADANIE WYDAJNOŚCI ROZPROSZONEGO SYSTEMU TELEKOMUNIKACYJNEGO VoIP” - Sylwester Kaczmarek, Sebastian Zaprzalski
  • AUTORSKA IMPLEMENTACJA SYSTEMU WYMIANY NUMERACJI TELEFONICZNEJ POMIĘDZY OPERATORAMI VoIP” - Krzysztof Nowicki, Michał Pietrasiuk, Krzysztof Raszkowski
  • QUALITY MEASURE OF VOIP SERVICES IN CARRIER GRADE SYSTEMS” - Sylwester Kaczmarek, Maciej Krajewski

Prezentacja Sebastiana dotyczy testów wydajności systemu, zadanie polegało na sprawdzeniu wydajności i skalowalności rozproszonego systemu telekomunikacyjnego oraz sprawdzeniu czy zależność między ilością węzłów, a wydajnością, jest liniowa, czy też nie.
Michał z Krzysztofem przedstawią analizę dostępnych systemów wymiany numeracji E.164 pomiędzy operatorami  oraz nową koncepcję, która rozwiązuje problem wymiany numeracji w sposób różniący się od istniejących rozwiązań, ukazując inne podejście do problemu wymiany numeracji.
Moja prezentacja dotyczy pasywnego pomiaru jakości usług VoIP, opierającego się na analizie pakietów RTCP. Metoda ta pozwala na gromadzenie danych statystycznych jakości połączeń przy niskim wykorzystaniu zasobów systemu. Zgromadzone w ten sposób dane są podstawiane do modelu E, co pozwala na estymację oceny MOS każdego połączenia.

Szczegóły konferencji znajdują się na stronie http://www.it2010.gda.pl

PgCon 2010 - część 4

09 czerwiec 2010, Michał Szymański

Server Health Check - wykład  a właściwie szkolenie prowadzone przez najbardziej rozpoznawalnego konsultanta od Postgres’a - Josh Bergus’a. W ciągu trzech godzin Josh omówił kroki mające na celu zdiagnozowanie na ile instalacja Postgres’a jest ‘zdrowy’, czyli jak daleko jesteśmy od (jak to zostało nazwane) ‘ściany’. Gdzie ‘ściana’ to moment w czasie, w którym zaczną się lawinowo pojawiać problemy z wydajnością. Z ciekawych dla nas tematów została poruszona kwestia używania dysków SSD w instalacjach bazodanowych. Według autora prezentacji jeden dysk SSD może zastąpić nawet cztery tradycyjne dyski. Jednak w dalszym ciągu należy zachować ostrożność w stosowaniu tej technologii, ze względu na dość dużą awaryjność dysków SSD i duży rozrzut wydajności nawet w obrębie jednego producenta (a nawet jednego modelu).

Postgres-XC, Write-scalable, synchronous multi-master PostgreSQL cluster with shared nothing approach na tej prezentacji można było zapoznać się z pierwszymi wynikami testów Postgres’a w wersji klastrowej. Pierwsze pomiary wypadły naprawdę obiecująco. W odróżnieniu od MySQL Cluster wszystkie dane przechowywane są na dyskach. Zastosowano dwie metody rozpraszania danych na tzw. węzłach danych ang.data node (czyli serwerach gdzie przechowywane są dane), pierwsza metoda to duplikacja tabeli na kilkanaście węzłów, druga o rozpraszanie wierszy z tabeli między grupą węzłów (metoda rozpraszania wybierana jest w konfiguracji). W prezentowanym rozwiązaniu zagwarantowano pełną transakcyjność operacji bazodanowych co jest niewątpliwą zaletą w porównaniu z istniejącymi rozwiązaniami wspierającymi rozpraszanie danych dla Postgresa. Niestety PostgresXC jest na wczesnym etapie rozwoju i moim zdaniem wersja, którą można będzie wdrożyć produkcyjnie pojawi się za 1-3 lata.

Bardzo ciekawymi prezentacjami moim zdaniem były prezentacje z kategorii ’studium przypadku’. Jedną z takich prezentacji była historia udanego wdrożenia Postgresa w jednym z największych banków Brazylii Caixa Economica Federal. Postgres został zastosowany między innymi w systemie monitorowania 22tyś. bankomatów. Swoją drogą do dzisiaj nie mogę wyjść z podziwu dla otwartości instytucji państwowej w Brazylii na open-source’owe rozwiązania. W przypadku Caixa argumentem, który przeważył o zastosowaniu Postgres’a był argument finansowy - brak opłat licencyjnych za Postgresa.

Podobną prezentacje miał Jim Nasby z Enova Financial. Enovo używa Postgresa w głównym systemie obsługi klienta, aktualna wielkość ich bazy to 1.4TB, szczytowe obciążenie bazy to około 4000TPS i wielkość danych używanych w codziennej pracy to około 200GB. Jest to chyba jedna z większych (patrząc na wielkość bazy) baz Postgres’owych dla systemu OLTP. Prezentacje w formie slajdów można pobrać z TEGO miejsca.

Tematy proste ale czasami skomplikowane - transakcje

03 czerwiec 2010, Michał Szymański

Tematyką wytwarzaniem oprogramowaniem zajmuje się już ponad dziesięć lat i z moich obserwacji wynika, że są pewne tematy o których programiści/projektanci/architekci wiedzą, że są jednak ich wiedza na ten temat jest mocno wyrywkowa albo po prostu oparta na pewnych mitach. Pierwszy taki temat o którym chciałbym napisać to używanie transakcji w systemach informatycznych, tak się składa że ostatnio też  musiałem powrócić do tej tematyki w związku ze zmianami architektury naszego systemu.
Może na początek podam definicje transakcji, cytując za Wikipedią:

Transakcja - zbiór operacji na bazie danych, które stanowią w istocie pewną całość i jako takie powinny być wykonane wszystkie lub żadna z nich. Warunki jakie powinny spełniać transakcje bardziej szczegółowo opisują zasady ACID (Atomicity, Consistency, Isolation, Durability - Atomowość, Spójność, Izolacja, Trwałość).

Żeby operacja była transakcyjną musi spełniać zasady ACID i może warto ten skrót bardziej rozwinąć:

  • Atomowość transakcji - właściwość gwarantująca niepodzielność kroków w wykonywanej operacji. Czyli albo wszystkie kroki operacji zostają wykonane albo żaden z nich. Przykładem ilustrującym tą właściwość mogą być dwa kroki realizowane w trakcie transferu środków w systemie bankowym między dwoma kontami. Przy takiej operacji najpierw odejmujemy kwotę z jednego konta a później dodajemy tą kwotę do drugiego konta. Atomowość gwarantuje, że wykonana zostaną dwa kroki albo żaden z nich.
  • Spójność transakcji - gwarantuje, że po operacji system będzie spójny, inaczej mówiąc nie zostaną naruszone zasady integralności systemu. Najprostszym przykładem może być wstawienie wiersza w tabeli z obywatelami Polski gdzie kluczem unikalnym (czyli gwarantującym unikalność) jest zasada mówiąca, że każdy obywatel Polski ma unikalny PESEL (co w praktyce nie jest do końca prawdą bo zdarzały się przypadki, że ten numer nie jest unikalny co sugeruje, że w systemie pojawił się problem z transakcjami:) ).
  • Izolacyjność transakcji - gwarantuje, że dwie współbieżne operacje nie widzą efektów swojego działania do czasu zatwierdzenia transakcji (czyli operacji COMMIT). Ze względu na to, że gwarantując całkowitą izolacyjność transakcji tracimy na możliwości wykonywania równoległych operacji na danych w większości systemów możemy ustawiać tzw. poziom izolacji. O poziomie izolacji napiszę w dalszej część artykułu bo jest to jeden z tematów, który jest słabo znany przez programistów.
  • Trwałość - oznacza, że system potrafi udostępnić spójne i nienaruszone dane zapisane w ramach zatwierdzonych transakcji po awarii spowodowanej np. zanikiem napięcia.

Przy omawianiu ACID wspomniałem o czymś takim jak poziom izolacji, z moich obserwacji programiści często błędnie zakładają, że jak już wykonują operacje w transakcji nic złego nie może się zdarzyć. Niestety zwykle poziom izolacji jest tak ustawiony, że przy niektórych scenariuszach mogą się pojawić ‘ciekawe przypadki’. Wymagana jest świadomość jakie ‘złe rzeczy’ mogą się wydarzyć na określonych poziomach. Dlatego zacznę od listy ‘złych rzeczy’, które mogą się pojawić przy operacjach objętych transakcją:

  • dirty read - transakcja może przeczytać dane zapisane przez inną niezakończoną transakcje
  • nonrepeatable read - w transakcji ponownie odczytujemy dane, które wcześniej były odczytane w tej samej transakcji i okazuje się, że dane uległy modyfikacji w wyniku innej zakończonej transakcji (czyli były zmodyfikowane między kolejnymi odczytami)
  • phantom read - ponowne wykonanie zapytanie z tymi samymi warunkami wyszukiwania zwraca inny zbiór wierszy - inna zakończona transakcja dodała nowe wiersze.

Korzystając z określonego poziomu izolacji unikamy albo jesteśmy narażeni na wymienione problemy. Tabelka poniżej prezentuje na co jesteśmy narażeni w przypadku określonego poziomu izolacji:

Poziom izolacji Dirty Read Nonrepeatable Read Phantom Read
Read uncommitted Możliwe Możliwe Możliwe
Read committed Niemożliwe Możliwe Możliwe
Repeatable read Niemożliwe Niemożliwe Możliwe
Serializable Niemożliwe Niemożliwe Niemożliwe

Należy zaznaczyć, że nie wszystkie systemy wspierają wszystkie poziomy izolacji i trzeba mieć tego świadomość w trakcie pisania oprogramowania. Przykładowo Postgres wspiera tylko dwa poziomy - serializable i read committed chociaż teoretycznie dostępne są wszystkie.

Mogłoby się wydawać po dotychczasowej lekturze, że najlepiej dla tworzącego oprogramowania byłoby używać poziomu serializable, wtedy unikniemy wszystkich problemów i to jest ‘prawie’ prawdą. Prawie ponieważ problemów z transakcyjnością unikniemy ale niechybnie pojawią się problemy z wydajnością. Przy poziomie serializable wszystkie operacje wykonywane są szeregowo, w epoce gdzie producenci serwerów prześcigają się w ilości rdzeni takie ograniczenie jest nie do zaakceptowania bo większość operacji na serwerach z założenia wykonywanych jest równolegle.

Jeśli już uporządkowaliśmy wiedzę odnośnie transakcji na koniec warto wspomnieć jakie są możliwości zarządzania transakcjami w programach. Wyróżnia się trzy modele zarządzania transakcjami:

Local Transaction Model – w tym przypadku programista zarządza połączeniami do źródeł danych np. baz danych przez JDBC i wywołuje operacje zatwierdzenia (COMMIT) albo wycofania (ROLLBACK) transakcji na konkretnym połączeniu, właściwie programista zarządza połączeniami niż transakcjami. Model ten jest dobrze znany programistą którzy używają JDBC w Javie gdzie otwieramy połączenie do bazy i na tym połączeniu wywołujemy metody commit() i rollback(). Poniżej przykład stosowania transakcji przy operacjach na bazie z użyciem JDBC

……….
Connection conn = ds.getConnection();
conn.setAuoCommit(false);
try {
OPERACJA NA BAZIE
con.commit();
} catch (Exception e) {
conn.rollback();
throw e;
} finally {
stmt.close();
conn.close();
}

Programmatic Transaction Model – w tym modelu programista zarządza transakcjami a nie połączeniami. Przykładem takiego rozwiązania jest interfejs JTA w Javie. Pozwala on na wywołanie kilkunastu operacji na różnych źródłach danych w obrębie jednej transakcji. W związku z tym, że JTA to tylko interfejs w celu użycia mechanizmów zarządzania transakcjami trzeba użyć jakieś dostępnej implementacji, w przypadku Javy możemy użyć niezależnego serwera transakcji typu Atomikos albo BTM. Poniżej przykład zarządzania transakcjami z użyciem JTA, zwróćcie uwagę, że commit() wykonywany jest na obiekcie utm a nie na conn (połączeniu do bazy).

UserTransactionManager
utm=new UserTransactionManager();
utm.init();
utm.begin();
Connection conn = ds.getConnection();
OPERACJA NA BAZIE
conn.close();
utm.commit();

Declarative Transaction Model – w przypadku EJB nazywany Container Managed Transaction. W tym modelu kontener w którym jest osadzony program zarządza transakcjami, programista poprzez opis w XML albo korzystając z adnotacji opisuje, które operacje powinny rozpoczynać albo dołączać do istniejącej transakcji, może również zdecydować jaki stopień izolacji ma być ustawiony przy każdej operacji. Ten model używany jest w EJB w serwerach aplikacji zgodnych z standardem J2EE albo w frameworku Spring.

To tyle w pierwszym artykule z cyklu ‘Tematy proste ale..’, mam nadziej, że chociaż trochę wyjaśniłem tematykę użycia transakcji.

PgCon 2010 - część 3

28 maj 2010, Michał Szymański

Jeśli jesteście ciekawi jak wyglądają programiści bazy Postgres to TUTAJ parę fotek ze spotkania developerów.