Server MySQL adalah sistem multi-user: satu server dapat menerima koneksi dari banyak aplikasi, banyak orang, dan banyak mesin sekaligus. Setiap koneksi yang masuk membawa identitas berupa akun — dan server memutuskan apa yang boleh dilakukan koneksi tersebut berdasarkan akunnya. Sebelum kita bisa mengatur hak akses, GRANT, dan role pada chapter-chapter berikutnya, kita perlu memahami terlebih dahulu benda yang diatur: akun itu sendiri. Pada chapter ini kita membedah format user@host, mengintip daftar akun di tabel sistem mysql.user, memahami arti localhost versus wildcard %, lalu membandingkan USER() dengan CURRENT_USER() dan mengamati siapa saja yang sedang terhubung lewat SHOW PROCESSLIST.
User: Akun Koneksi, Bukan Orang #
Istilah user di MySQL tidak sama dengan manusia yang duduk di depan komputer. User adalah akun koneksi — sepasang nama user dan pola host yang server gunakan untuk mengenali siapa yang menelepon. Nama seperti aplikasi_toko bukanlah nama orang, melainkan identitas yang dipakai program kasir toko untuk membuka koneksi; budi_analyst adalah identitas yang dipakai seorang analis data ketika menjalankan query laporan.
Format identitas akun selalu user@host:
aplikasi_toko@localhost → akun bernama aplikasi_toko, hanya boleh konek dari mesin yang sama
budi_analyst@% → akun bernama budi_analyst, boleh konek dari host mana punPasangan ini utuh: aplikasi_toko@localhost dan [email protected] adalah dua akun berbeda yang boleh punya sandi dan hak akses berbeda pula. Server menyimpan seluruh akun di sebuah tabel sistem bernama mysql.user — satu baris per akun, lengkap dengan kolom sandi ter-hash, plugin autentikasi, dan lusinan kolom hak akses.
Mengintip Daftar Akun di mysql.user #
Karena mysql.user adalah tabel biasa, kita bisa membacanya dengan SELECT seperti tabel lain. Kita pilih hanya kolom yang aman untuk ditampilkan — user, host, dan plugin:
SELECT user, host, plugin FROM mysql.user ORDER BY user, host;Output yang Dihasilkan:
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)Empat akun di atas adalah akun bawaan hasil inisialisasi server. Tiga akun mysql.infoschema, mysql.session, dan mysql.sys adalah akun internal yang dipakai komponen sistem — kita tidak boleh memakainya untuk login aplikasi. Satu-satunya akun manusiawi di server latihan kita adalah root, akun administratif serba bisa yang sengaja dibatasi ke host localhost.
Arti host: localhost dan Wildcard % #
Bagian host pada akun menjawab satu pertanyaan: dari mana koneksi boleh datang. Dua nilai paling umum memiliki makna yang sangat berbeda:
| Nilai host | Arti | Kegunaan tipikal |
|---|---|---|
localhost | Koneksi dari mesin yang sama (Unix socket atau TCP 127.0.0.1) | Aplikasi dan server database satu mesin |
% | Konek dari host mana pun yang bisa menjangkau server | Akun untuk tim yang tersebar di banyak jaringan |
192.168.%.% | Hanya host pada subnet tertentu | Pembatasan per segmen jaringan kantor |
Wildcard % memang praktis, tetapi juga memperluas permukaan serangan: bila server dapat dijangkau dari jaringan publik, akun @'%' dapat dicoba login dari seluruh dunia. Kebijakan yang lebih aman adalah menuliskan pola host paling sempit yang masih cukup untuk kebutuhan — misalnya budi_analyst@'192.168.1.%' alih-alih budi_analyst@'%'.
root versus User Aplikasi #
root adalah akun dengan seluruh hak akses: membuat dan menjatuhkan database apa pun, mengubah akun orang lain, membaca tabel sistem, sampai mematikan server. Kekuasaan penuh ini membuat root praktis untuk administrasi, tetapi berbahaya bila dipakai sebagai akun aplikasi. Bayangkan aplikasi toko yang konek sebagai root, lalu kodenya mengandung celah SQL injection: penyerang yang menyelinap lewat celah itu mewarisi seluruh kekuasaan root — bisa DROP DATABASE atas semua database, membaca seluruh mysql.user, bahkan membuat akun backdoor untuk dirinya sendiri.
Praktik standar industri adalah membuat akun khusus per aplikasi — misalnya aplikasi_toko@localhost — lalu memberikan hak akses yang minimal. Dengan begitu kebocoran pada satu aplikasi tidak menjalar ke seluruh server. Pembuatan akun seperti ini kita praktikkan penuh pada chapter berikutnya.
USER() dan CURRENT_USER(): Identitas versus Akun yang Cocok #
MySQL menyediakan dua fungsi yang sering dikira sama. USER() melaporkan identitas klien: nama user yang kita kirim saat login ditambah host koneksi hasil resolusi server. CURRENT_USER() melaporkan akun yang benar-benar cocok di mysql.user — akun yang dipakai server sebagai dasar pemeriksaan hak akses. Kita lihat keduanya di sesi root kita:
SELECT USER() AS identitas_klien, CURRENT_USER() AS akun_cocok;Output yang Dihasilkan:
+-----------------+----------------+
| identitas_klien | akun_cocok |
+-----------------+----------------+
| root@localhost | root@localhost |
+-----------------+----------------+
1 row in set (0.00 sec)Kedua nilai sama karena koneksi lokal kita cocok tepat dengan root@localhost. Perbedaannya baru terlihat ketika pola host ikut bermain. Kita buat akun dengan wildcard % lalu masuk sebagai akun tersebut dari mesin yang sama:
DROP USER IF EXISTS 'budi_analyst'@'%';
CREATE USER 'budi_analyst'@'%' IDENTIFIED BY 'SandiKuat2026!';Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 0 rows affected (0.00 sec)Sekarang kita buka koneksi kedua dari terminal — persis seperti yang akan dilakukan pembaca di mesin sendiri, dengan port standar MySQL 3306:
-- @test-bash
MYSQL_PWD='SandiKuat2026!' mysql -h 127.0.0.1 -P 3306 -u budi_analyst -t -e "SELECT USER() AS identitas_klien, CURRENT_USER() AS akun_cocok;"Output yang Dihasilkan:
+------------------------+----------------+
| identitas_klien | akun_cocok |
+------------------------+----------------+
| budi_analyst@localhost | budi_analyst@% |
+------------------------+----------------+Mari kita bedah hasilnya: USER() melaporkan budi_analyst@localhost karena klien terhubung dari mesin yang sama, sedangkan CURRENT_USER() melaporkan budi_analyst@% — satu-satunya baris mysql.user yang cocok untuk nama user itu. Dua fungsi ini penting saat menelusuri masalah hak akses: pesan error MySQL selalu menyebut bentuk CURRENT_USER(), jadi kita tahu akun mana yang sedang kurang hak.
Melihat Siapa yang Sedang Terhubung: SHOW PROCESSLIST #
Selain daftar akun, kita juga bisa melihat koneksi yang hidup saat ini. SHOW PROCESSLIST menampilkan satu baris per koneksi — termasuk koneksi kita sendiri yang sedang menjalankan perintah ini:
-- @check
SHOW PROCESSLIST;Output yang Dihasilkan:
+------+-----------------+-----------------+------+---------+------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+-----------------+-----------------+------+---------+------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 6943 | Waiting on empty queue | NULL |
| 2440 | root | localhost:59846 | NULL | Query | 0 | init | SHOW PROCESSLIST |
+------+-----------------+-----------------+------+---------+------+------------------------+------------------+
2 rows in set, 1 warning (0.00 sec)Nilai kolom Id, Host, dan Time berubah-ubah setiap dijalankan — Id adalah nomor koneksi yang terus bertambah, Host memuat port acak klien, dan Time adalah detik sejak perintah terakhir koneksi itu. Yang stabil dan bermakna adalah User (akun pemilik koneksi), db (database yang sedang dipilih), Command (jenis aktivitas, misalnya Query, Sleep, atau Daemon), State, dan Info (teks perintah yang sedang berjalan). Baris event_scheduler adalah proses internal penjadwal yang selalu hadir; baris root adalah sesi kita sendiri. Dalam operasional sehari-hari, SHOW PROCESSLIST dipakai untuk menemukan query macet atau koneksi menggantung — lalu KILL <Id> mengakhirinya.
Membersihkan Latihan #
Akun latihan budi_analyst sudah selesai dipakai, jadi kita jatuhkan langsung dari terminal — masih sebagai root, tanpa memilih database apa pun. Klausa IF EXISTS membuat pembersihan ini aman diulang meskipun akunnya ternyata sudah tidak ada:
-- @test-bash
mysql -h 127.0.0.1 -P 3306 -u root -e "DROP USER IF EXISTS 'budi_analyst'@'%';"Referensi #
- Security — MySQL 8.4 Reference Manual
- The mysql System Schema — MySQL 8.4 Reference Manual
- SHOW PROCESSLIST Statement — MySQL 8.4 Reference Manual
- Connection Management — MySQL 8.4 Reference Manual
Kita kini memahami akun sebagai pasangan user@host yang hidup di tabel mysql.user, mengapa aplikasi harus punya akun sendiri, dan bagaimana membedakan identitas klien dari akun yang cocok. Pertanyaan berikutnya sudah menggantung: bagaimana caranya membuat akun-akun itu? Chapter berikutnya membedah CREATE USER, ALTER USER, RENAME USER, dan DROP USER lengkap dengan jebakan error 1396-nya.