BAB III EKSPLORASI INTERNAL MYSQL SERVER Bab ini akan membahas hasil eksplorasi mengenai sistem internal dari MySQL Server. Hasil eksplorasi terdiri dari arsitektur MySQL Server beserta subsistemnya, penanganan koneksi, pemutusan koneksi, dan penanganan perintah.
3.1 Arsitektur Server Mysql
Gambar III-1 Arsitektur MySQL Server III-1
III-2
Gambar III-1 menunjukkan arsitektur MySQL secara global. Arsitektur MySQL terdiri dari lima subsistem utama yang bekerjasama untuk melayani request dari client kepada MySQL server. Lima subsistem utama tersebut adalah : -
Query Engine
-
Storage Manager
-
Buffer Manager
-
Transaction Manager
-
Recovery Manager
3.1.1 Query Engine Subsistem Query Engine terdiri atas tiga komponen yang saling terkait: -
Syntax Parser
-
Query Optimizer
-
Execution Component
Syntax Parser bertugas mengurai perintah SQL yang didapat dari program menjadi bentuk yang dikenal oleh MySQL engine. Pemeriksaan sintaks perintah tersebut akan dilakukan oleh Syntax Parser bersamaan dengan verifikasi hak akses program terhadap obyek-obyek yang akan digunakan.
Query Optimizer bertugas menyederhanakan sintaks perintah untuk digunakan oleh Execution Component, yang selanjutnya akan menyiapkan execution plan yang paling efisien. Query Optimizer akan mencari indeks yang sebaiknya digunakan untuk memperoleh data secepat dan seefisien mungkin. Query Optimizer akan memilih satu dari beberapa execution plan yang telah dibuat sebelumnya dan selanjutnya membuat rencana eksekusi yang dipahami oleh Execution Component.
Execution Component bertugas menginterpretasikan execution plan dan meminta komponen lain untuk me-retrieve record berdasarkan informasi yang didapat.
III-3
3.1.2 Storage Manager Storage Manager berhubungan langsung dengan sistem operasi dalam hal penulisan data ke disk secara efisien. Fungsi storage berada di subsistem yang berbeda, sehingga MySQL engine beroperasi sejauh satu level abstraksi dengan sistem operasi. Oleh karena itu, pada sistem operasi yang memiliki mekanisme storage berbeda, keterbatasan ini menyebabkan hanya bagian storage dari kode yang dapat ditulisi. Dengan adanya komponen pendukung Function Libraries, Storage Manager dapat menulis ke disk semua data di tabel user, indeks, log, dan data sistem internal.
3.1.3 Buffer Manager Subsistem Buffer Manager menangani hal-hal terkait manajemen memori antara request data oleh Query Engine dan Storage Manager. Cache yang digunakan untuk result set caching, sebagai bentuk optimalisasi penggunaan memori yang mencegah duplikasi request ke Storage Manager, dikelola di Buffer Manager.
Buffer Manager juga melakukan caching terhadap record baru sambil menunggu kesiapan tabel dan indeks tujuan. Jika dibutuhkan data baru, data tersebut akan diminta dari Storage Manager dan ditempatkan di buffer sebelum dikirim ke Query Engine.
3.1.4 Transaction Manager Transaction Manager bertugas memfasilitasi konkurensi dalam akses data. Subsistem ini menyediakan fasilitas locking yang memungkinkan beberapa user mengakses data sekaligus, namun tetap mendukung konsistensi basis data, tanpa merusak data dengan cara apapun. Kontrol transaksi ditangani oleh subkomponen Lock Manager, yang melakukan dan melepaskan lock terhadap objek-objek berbeda yang sedang dilibatkan dalam transaksi. Terdapat Transaction Manager pada setiap handler transactional table untuk menangani locking dan masalah konkurensi.
III-4
3.1.5 Recovery Manager Recovery Manager bertugas menyimpan salinan data untuk di-retrieve jika suatu saat terjadi kehilangan data. Recovery Manager juga mencatat log perintah yang melakukan modifikasi terhadap data dan event penting lainnya yang terjadi di basis data. Sampai saat ini, hanya handler tabel InnoDB dan BDB yang memiliki manajemen recovery. Handler MyISAM tidak memiliki prosedur recovery untuk transaksi, namun memiliki
mekanisme
penanganan
outage
pada
server.
Mekanisme
ini
mengaplikasikan fitur recovery tertentu yang dapat “memperbaiki” segala inkonsistensi internal yang mungkin terjadi sebagai dampak dari crash. Inkonsistensi yang umum terjadi terkait dengan update yang tidak dilakukan dengan baik pada indeks atau penulisan record yang tidak lengkap ke basis data.
3.1.6 Interaksi antar komponen Query Engine meminta agar data yang dibaca dari atau ditulis ke Buffer Manager memenuhi query user. Query Engine memerlukan Transaction Manager untuk meminta lock terhadap data untuk menjamin konkurensi. Dalam operasi create dan drop tabel, Query Engine akan mengakses langsung Storage Manager tanpa melalui Buffer Manager untuk membuat atau menghapus file di filesystem.
Buffer Manager meng-cache data dari Storage Manager untuk memungkinkan retrieval data yang efisien oleh Query Engine. Buffer Manager memerlukan Transaction Manager untuk melakukan pemeriksaan status lock terhadap suatu data sebelum melakukan operasi modifikasi berikutnya.
Untuk melakukan lock terhadap data di memori, Transaction Manager memerlukan Query Cache, sedangkan untuk melakukan lock terhadap data di filesystem, Transaction Manager memerlukan Storage Manager.
Recovery Manager menggunakan Storage Manager untuk menyimpan log perintah/event dan backup data di filesystem. Recovery Manager memerlukan
III-5
Transaction Manager untuk memperoleh lock terhadap file log yang sedang ditulis. Recovery Manager juga menggunakan Buffer Manager selama recovery dari crash.
Storage Manager bergantung pada filesystem dari sistem operasi dalam hal penyimpanan dan retrieval data yang persisten. Storage Manager memerlukan Transaction Manager untuk memperoleh informasi status lock.
3.2 Penanganan Transaksi Berikut adalah langkah-langkah interaksi antar komponen MySQL server dan antara MySQL server dengan client ketika melakukan suatu transaksi: -
Client mengirimkan perintah start transaction
-
Client mengirimkan query yang meminta perubahan terhadap data
-
Query tersebut di-parse, preproses, di-verifikasi keamanannya dan akhirnya dioptimisasi untuk kemudian dikirimkan kepada Query Execution Engine
-
Query Execution Engine kemudian akan mengoper request kepada Transaction Manager
-
Transaction Manager akan berinteraksi dengan Log Manager untuk mencatat log perubahan
-
Untuk menjamin atomicity, Transaction Manager akan berkoordinasi dengan Scheduler untuk mendapatkan lock terhadap data yang disimpan oleh Lock Manager
-
Jika Transaction Manager sudah mendapatkan lock dari data, Scheduler akan mengirimkan request kepada Resource Manager untuk mendapatkan file yang mengandung data tersebut
-
Resource Manager akan menerjemahkan request menjadi page request dan mengirimkan request tersebut kepada Buffer Manager
-
Buffer Manager meletakkan page yang bersesuaian di memory setelah membacanya dari disk melalui Storage Manager
-
Ketika data sudah ditransfer ke memory,Scheduler akan melakukan update terhadap data
III-6
-
Ketika perintah commit yang menandakan akhir transaksi diberikan, Scheduler akan melepas lock terhadap data dan memindahkan data tersebut ke tempat yang persisten.
3.3 Protokol MySQL Pada subbab ini akan dibahas mengenai protokol MySQL yang merupakan DBMS yang akan digunakan untuk implementasi solusi dari tugas akhir ini. Informasi mengenai field-field paket beserta ukurannya secara lengkap dapat dilihat di lampiran A.
Pada protokol MySQL terdapat dua jenis interaksi antara client dan server yaitu interaksi handshake yang dilakukan pada saat client melakukan koneksi dan interaksi perintah setelah handshake berhasil dilakukan.
Ketika client melakukan koneksi ke server, langkah-langkah handshaking-nya adalah sebagai berikut: 1. Server mengirimkan kepada client : handshake initialisation packet yang berisi informasi mengenai versi protokol, versi server, dan thread id yang merupakan id koneksi. 2. Client mengirimkan kepada server : client authentication packet yang berisi informasi mengenai username, password, dan nama database yang akan digunakan. 3. Server mengirimkan kepada client : OK packet yang menyatakan tidak ada kesalahan atau Error packet jika ditemukan kesalahan.
Ketika client memberikan perintah ke server, maka client akan mengirimkan paket command yang terdiri dari satu byte perintah dan n byte argument. Kemudian server akan mengirimkan jawaban berupa paket OK jika perintah berhasil dilakukan, paket result set jika perintah mengembalikan data atau paket Error jika perintah salah.
III-7
Gambar III-2 Sequence diagram client mengirimkan command insert
Pada Gambar III-2 dapat dilihat ketika client menginisiasi koneksi ke server (mysqld), maka server akan memanggil fungsi handle_connection_socket() yang memanggil system call accept() yang membentuk koneksi TCP kemudian menciptakan thread baru dengan fungsi create_new_thread(). Thread baru tersebut akan menangani perintah dari client dan mengurus resource koneksi. Do_command() berfungsi untuk membaca paket dari jaringan dan membuka header-nya sehingga perintah dapat diidentifikasi. perintah tersebut kemudian menjadi parameter dari fungsi dispatch_ command() yang akan memanggil fungsi yang sesuai dengan perintah yang ditentukan. Pada contoh di atas client mengirim perintah INSERT sehingga akan dieksekusi fungsi mysql_insert() kemudian thread yang bersangkutan akan mengirim result packet yang menyatakan hasil dari perintah tersebut kembali kepada client.
3.4 Penanganan Koneksi Untuk setiap koneksi yang diterima dari client, MySQL server akan membuat thread baru untuk menangani request dari client tersebut. Deskriptor dari thread tersebut dibungkus di dalam kelas yang bernama THD (Lampiran B).
III-8
int main(int argc, char **argv) { _cust_check_startup(); (void) thr_setconcurrency(concurrency); init_ssl(); server_init(); init_server_components(); start_signal_handler(); acl_init((THD *)0, opt_noacl); init_slave(); create_shutdown_thread(); create_maintenance_thread();
// 'bind' + 'listen'
handle_connections_sockets(0); DBUG_PRINT("quit",("Exiting main thread")); exit(0); }
Program utama yang bernama mysqld akan menginisialisasi komponen, melakukan listen di port yang ditentukan serta siap menerima koneksi baru di fungsi handle_connections_sockets.
handle_connections_sockets (arg __attribute__((unused)) { if (ip_sock != INVALID_SOCKET) { FD_SET(ip_sock,&clientFDs); DBUG_PRINT("general",("Waiting for connections.")); while (!abort_loop) { new_sock = accept(sock, my_reinterpret_cast(struct sockaddr*) (&cAddr), &length); thd= new THD; if (sock == unix_sock) thd->host=(char*) localhost; create_new_thread(thd); // membuat thread baru }
Pada fungsi handle_connections_sockets terdapat satu loop utama yang akan siap untuk menerima koneksi dari client kemudian menghidupkan objek THD dan mengoper objek THD tersebut ke fungsi create_new_thread yang akan menciptakan thread baru. create_new_thread(THD *thd) { pthread_mutex_lock(&LOCK_thread_count); pthread_create(&thd->real_id,&connection_attrib, handle_one_connection //fungsi yang dieksekusi oleh thread (void*) thd)); pthread_mutex_unlock(&LOCK_thread_count); }
III-9
3.5 Eksekusi Perintah Fungsi handle_one_connection merupakan fungsi yang dipanggil ketika thread baru diciptakan. Fungsi ini menerima objek THD yang menjadi deskriptor koneksi yang unik untuk masing-masing thread. Fungsi ini akan mengurus keutuhan koneksi seperti melakukan perintah melalui fungsi do_command(), menutup koneksi serta membereskan resource memory jika terjadi crash. handle_one_connection(THD *thd) { init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); while (!net->error && net->vio != 0 && !thd->killed) { if (do_command(thd)) // ! break; } close_connection(net); end_thread(thd,1); packet=(char*) net->read_pos;
Fungsi do_command akan membuka paket, memeriksa isinya, kemudian mengirimkan paket tersebut ke fungsi dispatch_command yang akan mengeksekusi perintah sesuai dengan query yang diberikan.
bool do_command(THD *thd) { net_new_transaction(net); packet_length=my_net_read(net); packet=(char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; dispatch_command(command,thd, packet+1, (uint) packet_length); }
3.6 Pemutusan Koneksi Pada saat MySQL server mendeteksi ada client yang terputus, maka akan dipanggil fungsi close_connection yang membereskan resource TCP dan end_thread yang akan membereskan resource objek THD. Fungsi end_thread akan memanggil method dari objek THD yang bernama cleanup yang berfungsi untuk mendealokasi memory
III-10
mengenai informasi tabel, melepas lock tabel, membereskan query cache dan merollback transaksi yang belum commit.
void end_thread(THD *thd, bool put_in_cache) { DBUG_ENTER("end_thread");
thd->cleanup(); (void) pthread_mutex_lock(&LOCK_thread_count); thread_count--; delete thd;
void THD::cleanup(void) { DBUG_ENTER("THD::cleanup"); { ha_rollback(this); xid_cache_delete(&transaction.xid_state); } if (locked_tables) { lock=locked_tables; locked_tables=0; close_thread_tables(this); } mysql_ha_flush(this, (TABLE_LIST*) 0, MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE); hash_free(&handler_tables_hash); delete_dynamic(&user_var_events); hash_free(&user_vars); close_temporary_tables(this);
3.7 Objek THD Objek THD merupakan objek yang diciptakan ketika ada client yang melakukan koneksi ke MySQL server. Objek ini berfungsi sebagai deskriptor dari koneksi tersebut. Sebagai deskriptor dari koneksi, objek THD ini menyimpan informasi antara lain mengenai basis data yang digunakan, nama dan password client ketika melakukan koneksi, informasi mengenai alamat IP dan port, transaksi dan informasi lain yang spesifik terhadap koneksi. Informasi-informasi yang disimpan di dalam objek THD dapat dikelompokkan seperti pada tabel III-1.
III-11
Tabel III-1 Member Objek THD Kelompok Member
Keterangan
Transaksi
savepoint, stmt,all,
Struktur yang berisi informasi mengenai
xid_state,on
transaksi seperti savepoint, start transaction, statement di dalam transaksi.
Basis data
db,db_length
Informasi mengenai nama basis data yang sedang digunakan
Koneksi
security_ctx, remote,
Struktur yang berisi keterangan mengenai
net,packet
nama client, password, dan alamat socket dari client yang didapat ketika client melakukan koneksi ke server..
Handler
ha_data[0]-ha_data[13]
data Lock
Penampung untuk handler data yang spesifik terhadap storage engine.
lock_info, main_lock_id,
Informasi mengenai lock terhadap data
lock_id,global_read_lock Query
Thread
query_id, select_number, Informasi mengenai query yang dieksekusi open_tables,
dan tabel-tabel yang digunakan ketika
used_tables,stmt_arena
melakukan query
Thread_id, variables,
Informasi mengenai id dari koneksi, variabel
status_var
lokal terhadap thread dan statistik yang spesifik terhadap thread seperti lama koneksi, dan jumlah query.