Spis tre ci
Przedmowa ...............................................................................................................................9
1. Historia i architektura MySQL ..................................................................................... 15
Historia MySQL 15
Architektura MySQL 17
2. Praca z kodem ród owym MySQL ............................................................................. 31
Powloka Uniksa 31
BitKeeper 31
Przygotowywanie systemu do budowania MySQL z drzewa BitKeepera 34
Budowanie MySQL z drzewa BitKeepera 35
Budowanie z dystrybucji ródlowej 37
Instalowanie MySQL w katalogu systemowym 38
Uklad katalogów z kodem ródlowym 38
Przygotowywanie systemu do uruchomienia MySQL w debugerze 40
Wycieczka po kodzie ródlowym w towarzystwie debugera 40
Podstawy pracy z gdb 41
Wyszukiwanie definicji w kodzie ródlowym 44
Interesuj ce punkty wstrzymania i zmienne 45
Modyfikowanie kodu ródlowego 45
Wskazówki dla koderów 47
Aktualizowanie repozytorium BitKeepera 50
Zglaszanie poprawki 51
3. Podstawowe klasy, struktury, zmienne i interfejsy API ............................................53
THD 53
NET 58
TABLE 58
Field 58
Spis tre ci | 5
Narz dziowe wywolania API 65
Makra preprocesora 68
Zmienne globalne 70
4. Komunikacja mi dzy klientem a serwerem ............................................................... 73
Przegl d protokolu 73
Format pakietu 73
Relacje mi dzy protokolem MySQL a warstw systemu operacyjnego 74
Uzgadnianie pol czenia 75
Pakiet polecenia 80
Odpowiedzi serwera 83
5. Zmienne konfiguracyjne .............................................................................................89
Zmienne konfiguracyjne: samouczek 89
Interesuj ce aspekty konkretnych zmiennych konfiguracyjnych 96
6. W tkowa obs uga da ...........................................................................................115
W tki kontra procesy 115
Implementacja obslugi da 117
Problemy programowania w tkowego 121
7. Interfejs mechanizmów sk adowania .......................................................................127
Klasa handler 127
Dodawanie wlasnego mechanizmu skladowania do MySQL 142
8. Dost p wspó bie ny i blokowanie ............................................................................ 163
Mened er blokad tabel 164
9. Parser i optymalizator ............................................................................................... 169
Parser 169
Optymalizator 172
10. Mechanizmy sk adowania ........................................................................................ 195
Wspólne cechy architektury 196
MyISAM 196
InnoDB 202
Memory (Heap) 204
MyISAM Merge 205
NDB 205
Archive 206
Federated 207
6 | Spis tre ci
11. Transakcje ..................................................................................................................209
Implementowanie transakcyjnego mechanizmu skladowania 209
Implementowanie podklasy handler 210
Definiowanie handlertona 212
Praca z pami ci podr czn zapyta 214
Praca z binarnym dziennikiem replikacji 214
Unikanie zakleszcze 215
12. Replikacja ....................................................................................................................217
Przegl d 217
Replikacja oparta na instrukcjach i na wierszach 218
Dwuw tkowy serwer podrz dny 219
Konfiguracja z wieloma serwerami nadrz dnymi 219
Polecenia SQL ulatwiaj ce zrozumienie replikacji 220
Format dziennika binarnego 223
Tworzenie wlasnego narz dzia do replikacji 227
Skorowidz .............................................................................................................................229
Spis tre ci | 7
ROZDZIA 6.
W tkowa obs uga da
Podczas pisania kodu serwera programista staje przed dylematem: czy obslugiwa dania
za pomoc w tków, czy procesów? Oba podej cia maj swoje zalety i wady. Od samego pocz tku
MySQL korzystal z w tków. W tym rozdziale uzasadnimy w tkow obslug da w serwerze
MySQL, a tak e omówimy jej wady i zalety oraz implementacj .
W tki kontra procesy
By mo e najwa niejsz ró nic mi dzy procesem a w tkiem jest to, e w tek potomny wspól-
dzieli stert (globalne dane programu) z w tkiem macierzystym, a proces potomny  nie.
Ma to pewne konsekwencje, które trzeba uwzgl dni podczas wybierania jednego albo drugiego
modelu.
Zalety w tków
W tki s implementowane w bibliotekach programistycznych i systemach operacyjnych z nast -
puj cych powodów:
" Zmniejszone wykorzystanie pami ci. Koszty pami ciowe zwi zane z tworzeniem nowego
w tku s ograniczone do stosu oraz do pami ci ewidencyjnej u ywanej przez mened er
w tków.
" Dost p do globalnych danych serwera bez u ycia zaawansowanych technik. Je li dane mog
zosta zmodyfikowane przez inny dzialaj cy równolegle w tek, wystarczy chroni odpo-
wiedni sekcj za pomoc blokady ze wzajemnym wykluczaniem, zwanej muteksem (opi-
sywanej w dalszej cz ci rozdzialu). Je li nie ma takiej mo liwo ci, dost p do globalnych
danych mo na uzyskiwa w taki sposób, jakby nie bylo adnych w tków.
" Tworzenie w tku zajmuje znacznie mniej czasu ni tworzenie procesu, poniewa nie trzeba
kopiowa segmentu sterty, który mo e by bardzo du y.
" Program szereguj cy w j drze szybciej przel cza konteksty mi dzy w tkami ni mi dzy
procesami. Dzi ki temu w mocno obci onym serwerze procesor ma wi cej czasu na wyko-
nywanie rzeczywistej pracy.
115
Wady w tków
W tki odgrywaj wa n rol we wspólczesnych systemach komputerowych, ale maj równie
pewne wady:
" Pomylki programistyczne s bardzo kosztowne. Awaria jednego w tku powoduje zalama-
nie calego serwera. Jeden wyrodny w tek mo e uszkodzi globalne i zaklóci dzialanie
innych w tków.
" atwo popelni pomylk . Programista musi stale my le o problemach, jakie mo e spowo-
dowa jaki inny w tek, oraz o tym, jak ich unikn . Niezb dna jest bardzo defensywna
postawa.
" Wielow tkowe serwery s znane z usterek synchronizacyjnych, które s trudne do odtwo-
rzenia podczas testów, ale ujawniaj si w bardzo zlym momencie w rodowiskach produk-
cyjnych. Wysokie prawdopodobie stwo wyst powania takich usterek jest nast pstwem
wspóldzielenia przestrzeni adresowej, co znacznie zwi ksza stopie interakcji mi dzy
w tkami.
" W pewnych okoliczno ciach rywalizacja o blokady mo e wymkn si spod kontroli. Je li
zbyt wiele w tków próbuje jednocze nie pozyska ten sam muteks, mo e to doprowadzi
do nadmiernego przel czania kontekstów: procesor przez wi kszo czasu zamiast u ytecz-
nej pracy wykonuje program szereguj cy.
" W systemach 32-bitowych przestrze adresowa procesu jest ograniczona do 4 GB. Ponie-
wa wszystkie w tki wspóldziel t sam przestrze adresow , teoretycznie caly serwer
ma do dyspozycji 4 GB pami ci RAM, nawet je li w komputerze zainstalowano znacznie
wi cej fizycznej pami ci. W praktyce przestrze adresowa robi si bardzo zatloczona przy
znacznie mniejszym limicie, gdzie okolo 1,5 GB w Linuksie x86.
" Zatloczona 32-bitowa przestrze adresowa stwarza jeszcze jeden problem: ka dy w tek
potrzebuje troch miejsca na stos. Kiedy stos zostaje przydzielony, to nawet je li w tek ko-
rzysta z niego w minimalnym stopniu, konieczne jest zarezerwowanie cz ci przestrzeni
adresowej serwera. Ka dy nowy w tek ogranicza miejsce, które mo na przeznaczy na
stert . Je li wi c nawet w komputerze jest du o fizycznej pami ci, mo e si okaza , e nie da
si jednocze nie zaalokowa du ych buforów, uruchomi wiele wspólbie nych w tków
oraz zapewni ka demu z nich du o miejsca na stos.
Zalety rozwidlonych procesów
Wady w tków odpowiadaj zaletom korzystania z oddzielnych procesów:
" Pomylki programistyczne nie s tak katastrofalne. Cho niekontrolowany proces mo e
zaklóci dzialanie calego serwera, jest to znacznie mniej prawdopodobne.
" Trudniej popelni pomylk . Przez wi kszo czasu programista mo e my le tylko o jed-
nym w tku wykonania, nie martwi c si o potencjalnych intruzów.
" Pojawia si znacznie mniej fantomowych usterek. Kiedy wyst pi jaka usterka, zwykle
mo na latwo j odtworzy . Ka dy rozwidlony proces ma wlasn przestrze adresow , wi c
stopie ich wzajemnej interakcji jest znacznie mniejszy.
" W systemach 32-bitowych ryzyko wyczerpania przestrzeni adresowej jest du o mniejsze.
116 | Rozdzia 6. W tkowa obs uga da
Wady rozwidlonych procesów
Aby podsumowa nasz przegl d, wymieni wady rozwidlonych procesów, które s lustrzanym
odbiciem zalet w tków:
" Wykorzystanie pami ci jest nieoptymalne. Podczas rozwidlania procesu potomnego kopio-
wane s du e segmenty pami ci.
" Wspóldzielenie danych mi dzy procesami wymaga u ycia specjalnych technik. Utrudnia
to dost p do globalnych danych serwera.
" Tworzenie procesu wi e si z wi kszymi kosztami na poziomie j dra. Konieczno kopio-
wania segmentu danych procesu macierzystego znacznie obni a wydajno . Linux jednak
odrobin tu oszukuje, stosuj c technik zwan kopiowaniem przy zapisie. Rzeczywiste
kopiowanie strony procesu macierzystego zachodzi dopiero wtedy, gdy zostanie ona zmo-
dyfikowana przez proces macierzysty lub potomny. Do tego momentu oba procesy u ywaj
jednej strony.
" Przel czanie kontekstów mi dzy procesami jest bardziej czasochlonne, poniewa j dro musi
przel czy strony, tabele deskryptorów plików oraz inne dodatkowe informacje kontekstowe.
Serwer ma mniej czasu na wykonywanie rzeczywistej pracy.
Ogólnie rzecz bior c, serwer w tkowy jest idealny wtedy, gdy programy obslugi pol cze musz
wspóldzieli wiele danych, a programi cie nie brakuje umiej tno ci. Kiedy trzeba bylo wybra
model odpowiedni dla MySQL, wybór byl prosty. Serwer baz danych musi mie wiele wspól-
u ytkowanych buforów oraz innych wspóldzielonych danych.
Je li chodzi o umiej tno ci programistyczne, tych równie nie brakowalo. Podobnie jak dobry
je dziec staje si jedno ci ze swoim koniem, tak Monty stal si jedno ci z komputerem.
Bolalo go, kiedy widzial marnotrawienie zasobów systemowych. Byl pewien, e potrafi napisa
kod praktycznie pozbawiony usterek, poradzi sobie z problemami wspólbie no ci powodo-
wanymi przez w tki, a nawet pracowa z malym stosem. Co za ekscytuj ce wyzwanie! Oczy-
wi cie, wybral w tki.
Implementacja obs ugi da
Serwer oczekuje na pol czenia w swoim glównym w tku. Po odebraniu pol czenia przydziela
w tek do jego obslugi. W zale no ci od konfiguracji i bie cego stanu serwera, w tek mo e zosta
utworzony od zera albo przydzielony z pami ci podr cznej (puli) w tków. Klient przesyla
dania, a serwer je realizuje, dopóki klient nie wyda polecenia ko cz cego sesj (COM_QUIT)
albo sesja nie zostanie nieoczekiwanie przerwana. Po zako czeniu sesji, w zale no ci od konfi-
guracji i bie cego stanu serwera, w tek mo e zosta zako czony albo zwrócony do puli w t-
ków w oczekiwaniu na nast pne pol czenie.
Struktury, zmienne, klasy i interfejsy API
Je li chodzi o obslug w tków, prawdopodobnie najwa niejsza jest klasa THD, która reprezen-
tuje deskryptor w tku. Niemal ka da z funkcji parsera i optymalizatora przyjmuje obiekt THD
jako argument, najcz ciej pierwszy na li cie argumentów. Klas THD opisano szczególowo
w rozdziale 3.
Implementacja obs ugi da | 117
Podczas tworzenia w tku deskryptor jest umieszczany na globalnej li cie w tków I_List
threads (I_List<> to szablonowa klasa pol czonej listy; zob. sql/sql_list.h oraz sql/sql_list.c).
Listy tej u ywa si do trzech podstawowych celów:
" dostarczanie danych na u ytek polecenia SHOW PROCESSLIST;
" lokalizowanie docelowego w tku podczas wykonywania polecenia KILL;
" sygnalizowanie wszystkim w tkom, aby przerwaly prac , kiedy serwer jest zamykany.
Wa n rol odgrywa inna lista I_List: thread_cache. Jest ona u ywana w do nieocze-
kiwany sposób: jako metoda na przekazywanie obiektu THD utworzonego przez w tek glówny
do w tku oczekuj cego w puli, który zostal wyznaczony do obslugi bie cego dania. Wi cej
informacji mo na znale w funkcjach create_new_thread(), start_cached_thread() oraz
end_thread() w pliku sql/mysqld.cc.
Wszystkie operacje zwi zane z tworzeniem, ko czeniem i ledzeniem w tków s chronione
przez muteks LOCK_thread_count. Do obslugi w tków u ywa si trzech zmiennych warunku
POSIX. CONT_thread_count pomaga w synchronizacji podczas zamykania serwera, gwarantuj c,
e wszystkie w tki doko cz swoj prac przed zatrzymaniem w tku glównego. Warunek
COND_thread_cache jest rozglaszany, kiedy w tek glówny postanawia obudzi buforowany
w tek i skierowa go do obslugi bie cej sesji z klientem. Warunek COND_flush_thread_cache
jest u ywany przez buforowane w tki do sygnalizowania, e zaraz zako cz prac (podczas
zamykania serwera albo przetwarzania sygnalu SIGHUP).
Ponadto do obslugi w tków u ywa si kilku globalnych zmiennych stanu. S one opisane
w tabeli 6.1.
Wykonywanie da krok po kroku
P tla realizacji standardowych da select()/accept() znajduje si w funkcji handle_con-
nections_sockets() w pliku sql/mysqld.cc. Po do skomplikowanej serii testów, które spraw-
dzaj ewentualne bl dy wywolania accept() na ró nych platformach, docieramy do poni szego
fragmentu kodu:
if (!(thd= new THD))
{
(void) shutdown(new_sock,2);
VOID(closesocket(new_sock));
continue;
}
Tworzy on instancj THD. Po pewnych dodatkowych operacjach na obiekcie THD wykonanie
przenosi si do funkcji create_new_thread() w tym samym pliku sql/mysqld.cc. Po przepro-
wadzeniu kilku kolejnych testów oraz inicjalizacji dochodzimy to instrukcji warunkowej, która
ustala, jak zostanie uzyskany w tek obslugi dania. Istniej dwie mo liwo ci: u y buforowa-
nego w tku albo utworzy nowy.
Kiedy buforowanie w tków jest wl czone, stary w tek po obslu eniu dania klienta nie ko -
czy dzialania, lecz usypia. Gdy nowy klient nawi zuje pol czenie, serwer nie tworzy od razu
nowego w tku, lecz sprawdza, czy ma jakie u pione w tki w pami ci podr cznej. Je li tak, to
budzi jeden z nich, przekazuj c mu instancj THD jako argument.
118 | Rozdzia 6. W tkowa obs uga da
Tabela 6.1. Zmienne globalne zwi zane z w tkami
Definicja zmiennej Opis
int abort_loop
Znacznik, który sygnalizuje w tkom, e czas po sobie posprz ta i zako czy prac . Serwer
nigdy nie wymusza przerwania w tku, poniewa mog oby to doprowadzi do powa nego
uszkodzenia danych. Ka dy w tek jest napisany w taki sposób, aby monitorowa swoje
rodowisko i ko czy dzia anie, kiedy serwer tego za da.
int cached_thread_count
Zmienna stanu ledz ca liczb w tków, które zako czy y dzia anie i oczekuj na przydzielenie
do obs ugi innego dania. Mo na j obejrze w wynikach polecenia SHOW STATUS
pod nag ówkiem Threads_connected.
int kill_cached_thread
Znacznik, który sygnalizuje wszystkim buforowanym w tkom, e powinny zako czy dzia anie.
Buforowane w tki czekaj na warunek COND_thread_cache w funkcji end_thread().
Przerywaj prac , kiedy wykrywaj , e ten znacznik jest ustawiony.
int max_connections
Zmienna konfiguracyjna serwera okre laj ca maksymaln liczb po cze nieadministracyjnych,
które serwer mo e przyj . Po osi gni ciu tego limitu administrator bazy danych mo e nawi za
jedno dodatkowe po czenie administracyjne, aby jako rozwi za kryzys.
Dzi ki temu limitowi serwer mo e  wyhamowa  , zanim sparali uje system przez nadmierne
wykorzystanie zasobów.
Limit ten jest kontrolowany przez zmienn konfiguracyjn max_connections o domy lnej
warto ci 100.
int max_used_connections
Zmienna stanu ledz ca maksymaln liczb jednoczesnych po cze odnotowan od czasu
uruchomienia serwera. Jej warto mo na obejrze w wynikach polecenia SHOW STATUS
pod nag ówkiem Max_used_connections.
int query_id
Zmienna u ywana do generowania unikatowych identyfikatorów zapyta . Ka demu zapytaniu
przes anemu do serwera przypisuje si bie c warto tej zmiennej, która nast pnie
jest zwi kszana o 1.
int thread_cache_size
Zmienna konfiguracyjna serwera okre laj ca maksymaln liczb w tków w pami ci podr cznej
w tków.
int thread_count
Zmienna stanu ledz ca bie c liczb w tków. Jej warto mo na obejrze w wynikach
polecenia SHOW STATUS pod nag ówkiem Threads_cached.
int thread_created
Zmienna stanu ledz ca liczb w tków utworzonych od momentu uruchomienia serwera.
Jej warto mo na obejrze w wynikach polecenia SHOW STATUS pod nag ówkiem
Threads_created.
int thread_id
Zmienna u ywana do generowania unikatowych identyfikatorów w tków. Ka demu nowo
utworzonemu w tkowi przypisuje si bie c warto tej zmiennej, która nast pnie
jest zwi kszana o 1. Mo na j obejrze w wynikach polecenia SHOW STATUS pod nag ówkiem
Connections.
int thread_running
Zmienna stanu ledz ca liczb w tków, które obecnie odpowiadaj na zapytanie. Zwi kszana
o 1 na pocz tku funkcji dispatch_command() w pliku sql/sql_parse.cc i zmniejszana o jeden
na ko cu tej funkcji. Mo na j obejrze w wynikach polecenia SHOW STATUS pod nag ówkiem
Threads_running.
Cho buforowanie w tków mo e znacznie zwi kszy wydajno mocno obci onego systemu,
funkcj t pierwotnie dodano w celu rozwi zania pewnych problemów synchronizacji w Linuksie
na platformach Alpha.
Je li buforowanie w tków jest wyl czone albo aden buforowany w tek nie jest dost pny, w celu
obslu enia dania trzeba utworzy nowy w tek.
Implementacja obs ugi da | 119
Decyzja jest podejmowana w nast puj cym bloku:
if (cached_thread_count > wake_thread)
{
start_cached_thread(thd);
}
Funkcja start_cached_thread() z pliku sql/mysqld.cc budzi w tek, który obecnie nie obsluguje
dania, je li taki w tek istnieje. Warunek cached_thread_count > wake_thread gwarantuje
istnienie u pionego w tku, wi c funkcja nigdy nie jest wywolywana, je li nie ma adnych bufo-
rowanych w tków. Dotyczy to równie sytuacji, w której pami podr czna w tków jest
wyl czona.
Je li test dost pno ci buforowanych w tków zako czy si niepowodzeniem, kod przechodzi
do bloku else, gdzie zadanie utworzenia nowego w tku przypada poni szemu wierszowi:
if ((error=pthread_create(&thd->real_id, &connection_attrib,
handle_one_connection,
(void*) thd)))
Nowy w tek zaczyna si od funkcji handle_one_connection() w pliku sql/sql_parse.cc.
Funkcja handle_one_connection() po kilku testach i inicjalizacjach bierze si do roboty:
while (!net->error && net->vio != 0 && !thd->killed)
{
if (do_command(thd))
break;
}
Polecenia s akceptowane i przetwarzane dopóty, dopóki nie wyst pi warunek zako czenia
p tli. Oto mo liwe warunki wyj cia:
" Bl d sieciowy.
" W tek zostaje usuni ty poleceniem KILL przez administratora bazy danych albo przez zamy-
kany serwer.
" Klient wysyla danie COM_QUIT, informuj c serwer, e chce zako czy sesj . W takim przy-
padku funkcja do_command() z pliku sql/sql_parse.cc zwraca warto niezerow .
" Funkcja do_command() zwraca warto niezerow z jakiej innej przyczyny. Obecnie jedyn
inn mo liwo ci jest to, e nadrz dny serwer replikacji postanawia przerwa przesylanie
strumienia aktualizacji, którego serwer podrz dny (albo klient podszywaj cy si pod ser-
wer podrz dny) za dal poleceniem COM_BINLOG_DUMP.
Nast pnie funkcja handle_one_connection() przechodzi do fazy ko czenia w tku i porz d-
kowania. Kluczowym elementem tego segmentu kodu jest wywolanie funkcji end_thread()
z pliku sql/mysqld.cc.
Funkcja end_thread() zaczyna od pewnych dodatkowych czynno ci porz dkowych, a nast pnie
dociera do interesuj cego punktu: mo liwo ci umieszczenia obecnie wykonywanego w tku
w pami ci podr cznej. Decyzja jest podejmowana przez nast puj c instrukcj warunkow :
if (put_in_cache && cached_thread_count < thread_cache_size &&
! abort_loop && !kill_cached_threads)
Je li funkcja end_thread() postanowi zbuforowa w tek, wykonywana jest poni sza p tla:
while (!abort_loop && ! wake_thread && ! kill_cached_threads)
(void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
120 | Rozdzia 6. W tkowa obs uga da
P tla czeka, a w tek zostanie obudzony przez wywolanie start_cached_thread(), procedur
obslugi sygnalu SIGHUP albo procedur zamykania serwera. Je li sygnal budzenia pochodzi
od funkcji start_cached_thread(), parametr wake_thread ma warto niezerow . W takim
przypadku kod pobiera obiekt THD przekazany przez start_cached_thread() z listy thread_
cache, a nast pnie wraca (zwró my uwag na makro DBUG_VOID_RETURN) do funkcji handle_one_
connection(), aby zacz obslugiwanie nowego klienta.
Je li w tek nie zostanie przeniesiony do pami ci podr cznej, ostatecznie ko czy dzialanie przez
wywolanie pthread_exit().
Problemy programowania w tkowego
W MySQL wyst puj podobne komplikacje co w innych programach, które u ywaj w tków.
Wywo ania standardowej biblioteki C
Podczas pisania kodu, który mo e by wykonywany przez kilka w tków jednocze nie, trzeba
zachowa szczególn ostro no , je li chodzi o wywolywanie funkcji z zewn trznych bibliotek.
Zawsze istnieje pewne prawdopodobie stwo, e wywolany kod u ywa zmiennej globalnej,
pisze we wspóldzielonym deskryptorze pliku albo u ywa jakiego innego wspólnego zasobu,
nie gwarantuj c wzajemnego wykluczania. W takim przypadku trzeba zabezpieczy wywolanie
za pomoc muteksu.
Trzeba zachowa ostro no , a jednocze nie unika nadmiernej ochrony, która mo e spowo-
dowa spadek wydajno ci. Na przyklad mo na oczekiwa , e wywolanie malloc() jest bezpieczne
dla w tków. Inne funkcje, takie jak gethostbyname(), cz sto maj odpowiedniki bezpieczne dla
w tków. Skrypty konfiguruj ce kompilacj MySQL sprawdzaj , czy s one dost pne i u ywaj
ich, kiedy tylko jest to mo liwe. Je li odpowiednik bezpieczny dla w tków nie zostanie wykryty,
w ostateczno ci wl czany jest ochronny muteks.
Ogólnie rzecz bior c, MySQL oszcz dza sobie wielu zmartwie zwi zanych z bezpiecze stwem
w tków, implementuj c odpowiedniki wywola standardowej biblioteki C w warstwie przeno-
no ci w mysys oraz w bibliotece la cuchów w strings. Nawet je li ostatecznie wywolywana
jest biblioteka C, to w wi kszo ci przypadków odbywa si to za po rednictwem nakladki. Je li
w jakim systemie okazuje si , e wywolanie nie jest bezpieczne dla w tków, mo na latwo roz-
wi za problem przez dodanie muteksu do nakladki.
Blokady z wzajemnym wykluczaniem (muteksy)
W serwerze w tkowym kilka w tków mo e mie dost p do wspóldzielonych danych. W takim
przypadku ka dy w tek musi zagwarantowa , e b dzie mial dost p na wyl czno . W tym
celu stosuje si blokady z wzajemnym wykluczaniem, zwane te muteksami.
W miar jak zwi ksza si zlo ono aplikacji, trzeba zdecydowa , ilu muteksów u y i jakie
dane powinny by chronione przez ka dy z nich. Jedn skrajno ci jest utworzenie oddzielnego
muteksu dla ka dej zmiennej. Ma to t zalet , e rywalizacja o muteksy jest ograniczona do
minimum. S równie pewne wady: co si stanie, je li trzeba b dzie uzyska dost p do grupy
zmiennych w sposób atomowy? Konieczne b dzie oddzielne pozyskanie ka dego muteksu.
Problemy programowania w tkowego | 121
W takim przypadku trzeba zawsze pozyskiwa je w tej samej kolejno ci, aby unikn zaklesz-
cze . Cz ste wywolania funkcji pthread_mutex_lock() i pthread_mutex_unlock() doprowa-
dz do spadku wydajno ci, a programista pr dzej czy pó niej pomyli kolejno wywola i spo-
woduje zakleszczenie.
Na drugim ko cu spektrum znajduje si jeden muteks dla wszystkich zmiennych. Upraszcza
to prac programisty  wystarczy zalo y blokad podczas dost pu do zmiennej globalnej,
a pó niej j zwolni . Niestety, ma to bardzo negatywny wplyw na wydajno . Wiele w tków
musi niepotrzebnie czeka , kiedy jeden z nich uzyskuje dost p do zmiennej, która nie musi
by chroniona przed innymi.
Rozwi zaniem jest odpowiednie pogrupowanie zmiennych globalnych i utworzenie muteksu
dla ka dej grupy. Wla nie w ten sposób post pili twórcy MySQL.
W tabeli 6.2 znajduje si lista globalnych muteksów MySQL wraz z opisami grup zmiennych,
które s przez nie chronione.
Tabela 6.2. Globalne muteksy
Nazwa muteksu Opis muteksu
LOCK_Acl
Inicjalizowany, ale obecnie nieu ywany w kodzie. W przysz o ci mo e zosta usuni ty.
LOCK_active_mi
Chroni wska nik active_mi, który wskazuje deskryptor aktywnego podrz dnego serwera
replikacji. W tym momencie ochrona jest zb dna, poniewa warto active_mi nigdy
nie jest zmieniana wspó bie nie. Ochrona stanie si jednak konieczna, kiedy do serwera
zostanie dodana obs uga wielu serwerów nadrz dnych.
LOCK_bytes_received
Chroni zmienn stanu bytes_received, która ledzi liczb bajtów odebranych
od wszystkich klientów od momentu uruchomienia serwera. Nieu ywana w wersji 5.0
i nowszych.
LOCK_bytes_sent
Chroni zmienn stanu bytes_sent, która ledzi liczb bajtów wys anych do wszystkich
klientów od momentu uruchomienia serwera. Nieu ywana w wersji 5.0 i nowszych.
LOCK_crypt
Chroni wywo anie uniksowej biblioteki C crypt(), które nie jest bezpieczne dla w tków.
LOCK_delayed_create
Chroni zmienne i struktury zaanga owane w tworzenie w tku do obs ugi opó nionego
wstawiania. Opó nione operacje wstawiania natychmiast wracaj do klienta, nawet
je li tablica jest zablokowana  w takim przypadku s przetwarzane w tle przez w tek
opó nionego wstawiania.
LOCK_delayed_insert
Chroni list w tków opó nionego wstawiania I_List
delayed_threads.
LOCK_delayed_status
Chroni zmienne stanu ledz ce operacje opó nionego wstawiania.
LOCK_error_log
Chroni zapisy w dzienniku b dów.
LOCK_gethostbyname_r
Chroni wywo anie gethostbyname() w funkcji my_gethostbyname_r() w pliku
mysys/my_gethostbyname.c w systemach, w których biblioteka C nie oferuje wywo ania
gethostbyname_r().
LOCK_global_system_variables
Chroni operacje modyfikuj ce globalne zmienne konfiguracyjne z poziomu w tku
klienckiego.
LOCK_localtime_r
Chroni wywo anie localtime() w funkcji my_localtime_r() w pliku
mysys/my_pthread.c w systemach, w których biblioteka C nie oferuje wywo ania
localtime_r().
LOCK_manager
Chroni struktury danych u ywane przez w tek mened era, który obecnie jest odpowiedzialny
za okresowe wymuszanie zapisu tabel na dysku (je li ustawienie flush_time jest
niezerowe) oraz za porz dkowanie dzienników Berkeley DB.
122 | Rozdzia 6. W tkowa obs uga da
Tabela 6.2. Globalne muteksy  ci g dalszy
Nazwa muteksu Opis muteksu
LOCK_mapped_file
Chroni struktury danych i zmienne u ywane do operacji na plikach odwzorowanych
w pami ci. Obecnie funkcja ta jest wewn trznie obs ugiwana, ale nie jest u ywana
w adnej cz ci kodu.
LOCK_open
Chroni struktury danych i zmienne zwi zane z pami ci podr czn tabel oraz z otwieraniem
i zamykaniem tabel.
LOCK_rpl_status
Chroni zmienn rpl_status, która mia a by u ywana do bezpiecznej replikacji
z automatycznym przywracaniem danych. Obecnie jest to martwy kod.
LOCK_status
Chroni zmienne wy wietlane w wynikach polecenia SHOW STATUS.
LOCK_thread_count
Chroni zmienne i struktury danych zaanga owane w tworzenie lub niszczenie w tków.
LOCK_uuid_generator
Chroni zmienne i struktury danych u ywane przez funkcj SQL UUID().
THR_LOCK_charset
Chroni zmienne i struktury danych zwi zane z operacjami na zestawie znaków.
THR_LOCK_heap
Chroni zmienne i struktury danych zwi zane z pami ciowym mechanizmem sk adowania
(MEMORY).
THR_LOCK_isam
Chroni zmienne i struktury danych zwi zane z mechanizmem sk adowania ISAM.
THR_LOCK_lock
Chroni zmienne i struktury danych zwi zane z mened erem blokad tabel.
THR_LOCK_malloc
Chroni zmienne i struktury danych zwi zane z nak adkami na rodzin wywo a
malloc(). U ywany g ównie w wersji malloc() przeznaczonej do debugowania
(zob. mysys/safemalloc.c).
THR_LOCK_myisam
Chroni zmienne i struktury danych zwi zane z mechanizmem sk adowania MyISAM.
THR_LOCK_net
Obecnie u ywany do ochrony wywo ania inet_ntoa() w funkcji my_inet_ntoa()
w pliku mysys/my_net.c
THR_LOCK_open
Chroni zmienne i struktury danych, które ledz otwarte pliki.
Oprócz muteksów globalnych istnieje kilka muteksów osadzonych w strukturach lub klasach,
które slu do ochrony cz ci danej struktury lub klasy. Istnieje wreszcie kilka muteksów glo-
balnych o zasi gu plikowym (static) w bibliotece mysys.
Blokady odczytu-zapisu
Blokada na wyl czno nie zawsze jest najlepszym rozwi zaniem ochrony operacji wspólbie -
nych. Wyobra my sobie sytuacj , w której pewna zmienna rzadko jest modyfikowana tylko
przez jeden w tek, natomiast cz sto czytana przez wiele innych. Gdyby my u yli muteksu,
zwykle jeden w tek czytaj cy musialby czeka , a inny zako czy czytanie, cho moglyby one
wykonywa si wspólbie nie.
W takich sytuacjach lepiej sprawdza si inny typ blokady: blokada odczytu-zapisu. Blokady
odczytu mog by wspóldzielone, a blokady zapisu wzajemnie si wykluczaj . Zatem wiele
w tków czytaj cych mo e dziala wspólbie nie, pod warunkiem e nie ma w tku pisz cego.
Jak wida , blokada odczytu-zapisu mo e robi to samo co muteks i wi cej. Czemu wi c nie u y-
wa tylko blokad odczytu-zapisu? Jak mówi przyslowie, nie ma nic za darmo. Dodatkowe
funkcje wymagaj bardziej zlo onej implementacji. W rezultacie blokady odczytu-zapisu zaj-
muj wi cej cykli procesora, nawet gdy blokada zostanie pozyskana natychmiast.
Problemy programowania w tkowego | 123
Czytaj dalej...