@RolandoMySQLDBA telah menjawab pertanyaan secara akurat ... tetapi ia juga menunjukkan bahwa solusinya adalah "cepat dan kotor."
Dan itu adalah pernyataan yang sangat benar. :)
Hal yang menjadi perhatian saya di sini bukanlah dengan jawaban itu, melainkan bahwa pertanyaan awal tampaknya membuat asumsi yang salah:
Saya dapat meminta dua server dan bertanya yang mana adalah master, lalu melakukan semua pertanyaan dengan yang itu.
Masalahnya adalah bahwa dalam replikasi MySQL, master tidak pernah benar-benar menyadari bahwa itu adalah master.
Konsep "promosi untuk menguasai" sebenarnya bukan konsep replikasi asinkron MySQL. "Mempromosikan" server MySQL ke peran master adalah sesuatu yang terjadi "eksternal ke" server MySQL, sebagai lawan dari sesuatu yang terjadi "internal ke" server MySQL.
"Promosi ke master" tidak dilakukan oleh segala jenis penyediaan server, karena, secara teknis, setiap server MySQL yang mengaktifkan pencatatan biner adalah master, walaupun tidak pernah memiliki slave. SHOW MASTER STATUS
bekerja dengan cara yang persis sama dan mengembalikan hasil yang sama persis, budak atau tidak, dan master dengan 2 budak tidak lebih atau kurang master daripada master dengan 1 budak atau 0 budak. Demikian pula, master yang semua budaknya offline tetap sama besarnya dengan master, karena ketika budak kembali online, mereka akan mengambil replikasi di mana mereka tinggalkan.
Dalam arti tertentu, satu-satunya "kesadaran" pada bagian dari kedua server bukanlah apakah itu master, melainkan apakah itu adalah seorang budak (atau "tidak").
Itulah yang ditanyakan solusi Rolando: "apakah Anda seorang budak?" Jika jawabannya tidak, maka asumsinya adalah bahwa ini harus menjadi tuan ... yang ia juga tunjukkan sebagai asumsi yang salah jika STOP SLAVE;
dikeluarkan. Tetapi budak yang dihentikan masihlah seorang budak, jadi "bukan budak" (kapan saja) tidak sama dengan "menjadi tuan."
Tes serupa dapat dilakukan pada master yang diduga:
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
atau
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
Jika nilainya nol, maka utas slave slave tidak tersambung. Tes ini memiliki cacat yang sama, yaitu jika budak terputus secara administratif, terisolasi, atau gagal, maka tidak akan terhubung. Jadi ini juga tidak benar-benar menyelesaikan apa pun.
Lebih buruk lagi (untuk salah satu skenario ini) "tabel" information_schema.processlist adalah tabel virtual yang terwujud setiap kali dipilih, dan ini membutuhkan waktu dan biaya sumber daya. Semakin sibuk server Anda, semakin banyak biayanya, karena setiap aktivitas utas harus diintip ke dalam.
Solusi yang lebih ringan adalah:
SELECT @@global.read_only;
Pada seorang budak, Anda dapat / harus mengatur variabel global read_only
sehingga pengguna tanpa SUPER
hak istimewa tidak dapat menulisnya secara tidak sengaja (dan aplikasi Anda seharusnya tidak memilikinya SUPER
). Jika Anda secara manual "mempromosikan" budak ke peran utama, Anda SET GLOBAL read_only = OFF
dapat mengaktifkan penulisan. (Replikasi selalu dapat menulis ke budak, tidak peduli bagaimana ini diatur).
Tapi saya pikir, masih ada hal penting yang terlewatkan:
Saya akan mengusulkan bahwa aplikasi tidak harus membuat keputusan ini secara heuristik dalam pengaturan master / slave, dan tentu saja tidak berdasarkan koneksi-oleh-koneksi. Aplikasi harus menggunakan opsi konfigurasi yang sulit, atau aplikasi harus tetap tidak sadar dan tujuan koneksi database ditangani oleh sesuatu yang lain.
Atau, paling tidak, aplikasi tidak boleh beralih sampai master gagal, dan kemudian tidak boleh kembali dengan sendirinya.
Inilah mengapa saya mengatakan bahwa: setelah "keputusan" dibuat - oleh siapa pun atau apa pun - untuk menjadikan server lain master, aplikasi tidak dapat diizinkan dengan alasan apa pun untuk beralih kembali ke master asli, bahkan setelah itu kembali online , tanpa intervensi.
Katakanlah Anda menabrak bug dan ada crash yang dipaksakan oleh perangkat lunak; mysqld_safe
patuh memulai kembali mysqld
, dan pemulihan kerusakan InnoDB tampil dengan sempurna. Tapi itu butuh beberapa menit.
Sementara itu, master sedang down sehingga aplikasi Anda telah beralih ke slave. Transaksi telah dibuat, pesanan ditempatkan, dana ditransfer, komentar diposting, blog diedit, apa pun sistem Anda.
Sekarang, master asli kembali online.
Jika aplikasi Anda beralih kembali ke master asli, Anda berada di dunia yang benar-benar terluka, karena hal berikutnya yang mungkin terjadi adalah replikasi berhenti karena inkonsistensi, karena aplikasi Anda telah mengubah data pada slave di mean waktu. Anda sekarang memiliki dua server database dengan data tidak konsisten yang harus Anda rekonsiliasi secara manual. Jika ada dolar atau poin atau kredit yang terlibat, Anda sekarang memiliki saldo yang tidak cocok.
Jadi, sangat penting bahwa aplikasi tidak diizinkan untuk beralih kembali ke master asli tanpa campur tangan Anda.
Tunggu, apakah Anda baru saja menemukan masalah dengan skenario ini seperti yang saya jelaskan? Master telah gagal tetapi aplikasi Anda tidak akan menggunakan slave, karena ia berpikir slave masih slave dan bukan master ... information_schema.processlist
permintaan pada slave masih akan mengembalikan non-nol bahkan jika server master dimatikan .
Jadi tidak ada gunanya aplikasi menemukan sesuatu, karena Anda harus secara manual STOP SLAVE
agar tes itu berguna.
Mungkin pendekatan yang lebih baik jika Anda ingin aplikasi dapat beralih adalah mengkonfigurasi server dengan replikasi melingkar.
Replikasi melingkar memiliki masalah yang melekat sendiri, tetapi selama aplikasi Anda hanya selalu menulis ke satu server pada suatu waktu, sebagian besar masalah tersebut menjadi non-masalah. Dengan kata lain, kedua mesin selalu dan sekaligus merupakan master dan slave, dalam arti replikasi, tetapi aplikasi Anda, melalui beberapa mekanisme, selalu hanya menunjuk ke satu mesin sekaligus sebagai "master" di mana ia dapat dan harus menulis .
Anda tidak dapat menggunakan alat HA di server MySQL karena pemisahan mereka, tetapi Anda bisa menerapkannya dengan HAProxy berjalan di server aplikasi. Aplikasi terhubung ke "MySQL" di localhost, yang bukan MySQL sama sekali, tetapi sebenarnya HAProxy ... dan meneruskan koneksi TCP ke mesin MySQL yang sesuai.
HAProxy dapat menguji koneksi ke server MySQL dan hanya menawarkan lalu lintas ke mesin MySQL yang menerima koneksi dan memungkinkan otentikasi.
Kombinasi HAProxy yang berjalan di server aplikasi (permintaannya akan sumber daya tidak akan substansial dibandingkan dengan hal lain yang harus dilakukan server aplikasi - cukup banyak hanya mengikat soket dan mengabaikan muatannya) ... dan replikasi melingkar MySQL akan menjadi pendekatan yang mungkin saya ambil dalam contoh ini, berdasarkan apa yang diketahui dari pertanyaan.
Atau, untuk pengaturan ketat manual, lakukan sesuatu yang jauh lebih sederhana daripada "penemuan," seperti entri dalam /etc/hosts
file server aplikasi dengan nama host yang digunakan aplikasi untuk terhubung ke MySQL, yang dapat Anda perbarui secara manual - dengan asumsi promosi budak menjadi master dimaksudkan untuk menjadi proses manual.
Atau, sesuatu yang lebih kompleks, menggunakan Percona XtraDB Cluster. Untuk ini, Anda ingin menambahkan server ketiga, karena dengan 3 node di PXC, jika 2 server dapat melihat satu sama lain tetapi terisolasi dari 1 server (jika ketiganya masih berjalan) kedua server tetap berjalan dengan gembira tetapi 1 server meringkuk menjadi bola kecil dan menolak untuk melakukan apa pun karena menyadari itu pasti yang aneh. Ini berfungsi karena 2 menyadari mereka masih merupakan mayoritas dari node yang sedang online sebelum jaringan terpecah dan 1 menyadari bahwa itu bukan. Dengan PXC, tidak masalah server mana yang terhubung dengan aplikasi Anda.
Saya mengatakan semua ini adalah untuk mengatakan "tidak memiliki aplikasi jajak pendapat server untuk melihat mana yang merupakan master" karena itu akan menggigit Anda cepat atau lambat dan itu akan menggigit kinerja Anda sampai hari itu menggigit.