Bagaimana saya bisa mengekspor hak istimewa dari MySQL dan kemudian mengimpor ke server baru?

88

Saya tahu cara mengekspor / mengimpor basis data menggunakan mysqldump & tidak apa-apa, tetapi bagaimana cara mendapatkan hak istimewa ke server baru.

Untuk poin tambahan, sudah ada beberapa database yang sudah ada pada yang baru, bagaimana cara mengimpor hak server lama tanpa menghapus pasangan yang ada.

Server lama: 5.0.67-komunitas

Server baru: 5.0.51a-24 + lenny1

EDIT: Saya mendapat dump db 'mysql' dari Server Lama & sekarang ingin tahu cara yang tepat untuk bergabung dengan db 'mysql' di Server Baru.

Saya mencoba 'Impor' langsung menggunakan phpMyAdmin dan berakhir dengan kesalahan tentang duplikat (yang saya sudah bermigrasi secara manual).

Adakah yang punya cara elegan untuk menggabungkan kedua database 'mysql'?

Gareth
sumber
1. Apakah itu persyaratan bagi Anda untuk menggunakan PHPMyAdmin? Jika itu saya akan menulis beberapa instruksi khusus PHPMyAdmin untuk Anda. 2. Dari PHPMyAdmin jika Anda mencoba "memilih * dari batas mysql.user 1;" apakah Anda mendapatkan hasil atau kesalahan.
Bruno Bronosky
1
Seperti yang saya sebutkan di bawah, saya pikir skrip Richard's mygrants adalah cara yang baik untuk mendapatkan info hibah. Namun, Anda juga dapat mencoba mengedit file dump untuk mengomentari INSERT ke tabel pengguna untuk pengguna yang sudah ada. Hak istimewa untuk dbs yang dipulihkan dari server lama kemudian akan disalin. Jika Anda telah menetapkan hak istimewa secara manual untuk beberapa dbs yang Anda kembalikan ke kotak baru, cari nama-nama tabel ini di file privilege dan komentar juga. Jangan lupakan flush_privileges sesudahnya. Deskripsi yang baik dari mysql db di: grahamwideman.com/gw/tech/mysql/perms/index.htm
nedm

Jawaban:

169

Jangan main-main dengan mysql db. Ada lebih banyak hal yang terjadi di sana daripada hanya tabel pengguna. Taruhan terbaik Anda adalah perintah " SHOW GRANTS FOR". Saya memiliki banyak alias dan fungsi pemeliharaan CLI di .bashrc saya (sebenarnya .bash_aliases yang saya sumberkan di .bashrc). Fungsi ini:

mygrants()
{
  mysql -B -N $@ -e "SELECT DISTINCT CONCAT(
    'SHOW GRANTS FOR \'', user, '\'@\'', host, '\';'
    ) AS query FROM mysql.user" | \
  mysql $@ | \
  sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
}

Perintah mysql pertama menggunakan SQL untuk menghasilkan SQL yang valid yang disalurkan ke perintah mysql kedua. Hasilnya kemudian disalurkan melalui sed untuk menambahkan komentar cantik.

$ @ Pada perintah akan memungkinkan Anda untuk memanggilnya sebagai: mygrants --host = prod-db1 --user = admin --password = rahasia

Anda dapat menggunakan kit alat unix lengkap Anda pada seperti ini:

mygrants --host=prod-db1 --user=admin --password=secret | grep rails_admin | mysql --host=staging-db1 --user=admin --password=secret

Itulah cara yang tepat untuk memindahkan pengguna. ACL MySQL Anda dimodifikasi dengan SQL murni.

Bruno Bronosky
sumber
Ini sebenarnya adalah fungsi bash helper yang bekerja dengan sangat baik. Ambil output dari itu dan dapat berjalan di server baru dan hak istimewa akan dimasukkan dengan benar dan akurat.
Jeremy Bouse
1
Saya suka fungsi Anda, hari ini itu menyelamatkan saya banyak pekerjaan. Terima kasih, terima kasih, terima kasih ...
Fabio
2
Ini bagus tetapi memiliki satu kelemahan besar. "\" Tambahan ditambahkan ke garis bawah dalam nama-nama basis data, jadi jika Anda memiliki, misalnya, pengguna dengan hak khusus pada basis data yang disebut foo_bar, itu akan dirender sebagai foo \ _bar alih-alih foo_bar, sehingga tidak akan diimpor dengan benar . Paling tidak, ini terjadi jika Anda menyimpan output dari skrip Anda ke file SQL dan kemudian mengimpornya ke server baru. Saya belum mencoba penyaluran langsung ekspor dan impor dalam satu baris.
matteo
1
Hati-hati dengan perintah ini. Jika Anda memiliki dalam usertabel pengguna dengan host %, tetapi kemudian dalam dbtabel Anda memiliki entri hostdengan nilai eksplisit, entri-entri dalam dbtabel tidak diambil menggunakan metode ini.
Mitar
1
@matteo Tambahkan -rke perintah mysql ke-2 dalam fungsi dan escapes ganda tidak akan dihasilkan oleh mysql. misal:mysql -r $@
lifo
45

Ada dua metode untuk mengekstrak SQL Grants dari MySQL Instance

METODE # 1

Anda dapat menggunakan pt-show-grants dari Percona Toolkit

MYSQL_CONN="-uroot -ppassword"
pt-show-grants ${MYSQL_CONN} > MySQLUserGrants.sql

METODE # 2

Anda dapat meniru pt-show-grantsdengan yang berikut ini

MYSQL_CONN="-uroot -ppassword"
mysql ${MYSQL_CONN} --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql ${MYSQL_CONN} --skip-column-names -A | sed 's/$/;/g' > MySQLUserGrants.sql

Salah satu metode akan menghasilkan dump SQL murni dari hibah MySQL. Yang tersisa untuk dilakukan adalah menjalankan skrip di server baru:

mysql -uroot -p -A < MySQLUserGrants.sql

Cobalah !!!

RolandoMySQLDBA
sumber
1
pt-show-grants adalah persis apa yang Anda inginkan untuk ini, ini bekerja dengan baik.
Glenn Plas
Percona hanyalah kehebatan murni.
sjas
7
Tetapi jawaban # 2 sama baiknya dan akan bekerja tanpa perangkat lunak tambahan!
sjas
14

Jawaban Richard Bronosky sangat berguna bagi saya. Terimakasih banyak!!!

Berikut adalah variasi kecil yang bermanfaat bagi saya. Sangat membantu untuk mentransfer pengguna misalnya antara dua instalasi Ubuntu yang menjalankan phpmyadmin. Hanya buang hak istimewa untuk semua pengguna selain dari root, phpmyadmin dan debian-sys-Maint. Kode itu kemudian

mygrants()
{
mysql -B -N $@ -e "SELECT DISTINCT CONCAT(
'SHOW GRANTS FOR ''', user, '''@''', host, ''';'
) AS query FROM mysql.user WHERE user NOT IN ('root','phpmyadmin','debian-sys-maint')"  | \
mysql $@ | \
sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
}
rmldj
sumber
2
Jika Anda melihat contoh saya di mana saya grep rails_admindapat menyimpulkan bagaimana melakukan ini tanpa membuat fungsi khusus untuk setiap kasus tepi. Gunakan opsi "invert-match" grep seperti:mygrants --host=prod-db1 --user=admin --password=secret | grep -Ev 'root|phpmyadmin|debian-sys-maint' | mysql --host=staging-db1 --user=admin --password=secret
Bruno Bronosky
7

Atau, gunakan percona-toolkit (mantan maatkit) dan gunakan pt-show-grants(atau mk-show-grants) untuk tujuan itu. Tidak perlu skrip rumit dan / atau prosedur tersimpan.

MrkiMile
sumber
5

Anda dapat mysqldump database 'mysql' dan impor ke yang baru; flush_privileges atau restart akan diperlukan dan Anda pasti ingin mencadangkan db mysq yang ada terlebih dahulu.

Untuk menghindari penghapusan hak istimewa yang ada, pastikan untuk menambahkan daripada mengganti baris dalam tabel hak istimewa (db, kolom_priv, host, func, dll.).

nedm
sumber
Terima kasih @nedm. Sepertinya server cPanel yang mengganggu saya mencoba untuk melepaskan dbs tidak menunjukkan db 'mysql'. Kalau tidak, saya akan menguji dan menegaskan jawaban Anda. Setelah saya mengetahuinya saya akan memeriksa kembali. Terima kasih.
Gareth
Itu sangat disayangkan tetapi dapat dimengerti, Anda mungkin dicegah mengakses database apa pun tetapi yang secara langsung dimiliki oleh pengguna Anda pada db bersama.
Dave Cheney
Aduh, ya, tanpa akses ke 'mysql' akan sulit melakukan apa pun yang terkait dengan pengguna atau izin. Apakah Anda memiliki akses baris perintah? Bisakah Anda menjalankan mysqldump dari terminal atau baris perintah (BUKAN dari shell mysql)? mysqldump -u username -ppassword mysql> mysqldump.sql
nedm
Db 'mysql' dapat diakses dari Cpanel WHM jika saya masuk sebagai 'root'. Dari sana saya dapat mengakses versi phpmyadmin yang memiliki database 'mysql' yang berisi izin
Gareth
Menggabungkan ke dalam skema mysql yang ada, data yang diekstrak dari skema mysql melalui mysqldump hampir pasti bermasalah. Anda memanipulasi skema kompleks dengan hubungan yang dipaksakan, dll. Skema ini sangat kompleks, sehingga mereka menciptakan sintaks SQL khusus (GRANT, REVOKE, DROP USER, dll.) Untuk mengatasinya. Namun, ekstrak Anda hanya terdiri dari pernyataan INSERT. Saya kehabisan karakter di sini. Perlu saya lanjutkan?
Bruno Bronosky
4

Anda juga bisa melakukannya sebagai prosedur tersimpan:

CREATE PROCEDURE spShowGrants()
    READS SQL DATA
    COMMENT 'Show GRANT statements for users'
BEGIN
    DECLARE v VARCHAR(64) CHARACTER SET utf8;
    DECLARE c CURSOR FOR
    SELECT DISTINCT CONCAT(
        'SHOW GRANTS FOR ', user, '@', host, ';'
    ) AS query FROM mysql.user;
    DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;  
    OPEN c;
    WHILE TRUE DO
        FETCH c INTO v;
        SET @v = v;
        PREPARE stmt FROM @v;
        EXECUTE stmt;
    END WHILE;
    CLOSE c;
END

dan menyebutnya dengan

$ mysql -p -e "CALL spShowGrants" mysql

kemudian menyalurkan output melalui perintah sed Richards untuk mendapatkan cadangan dari hak istimewa.

Lenny
sumber
3

Sementara tampaknya jawaban @Richard Bronosky adalah yang benar, saya menemukan pertanyaan ini setelah mencoba memigrasi satu set database dari satu server ke server lain dan solusinya jauh lebih sederhana:

server1$ mysqldump -u root -p --all-databases > dbdump.sql

server2$ mysql -u root -p < dbdump.sql

Pada titik ini, semua data saya terlihat jika saya masuk sebagai root, mysql.usertabel memiliki semua yang saya harapkan, tetapi saya tidak bisa masuk sebagai pengguna lain dan menemukan pertanyaan ini dengan asumsi saya harus kembali menerbitkan GRANTpernyataan.

Namun, ternyata server mysql hanya perlu di-restart agar hak istimewa yang diperbarui dalam mysql.*tabel berlaku:

server2$ sudo restart mysql

Semoga itu membantu orang lain mencapai apa yang seharusnya menjadi tugas sederhana!

Tom
sumber
Oh, dan situasiku sedikit berbeda dengan OP, dalam hal itu aku tidak mencoba untuk menggabungkan dump ke server dengan database / pengguna yang ada.
Tom
2
Anda sebenarnya tidak harus me-restart MySQLd untuk 'memperbarui hak istimewa'. Ini dapat dilakukan dengan perintah MySQL 'flush privilege;'
CloudWeavers
Masalah dengan pendekatan ini adalah bahwa ia hanya bekerja ketika versi MySQL sumber dan tujuan sama. Kalau tidak, Anda mungkin memiliki masalah karena tabel mysql.user sumber memiliki kolom yang berbeda dari tabel mysql.user tujuan, misalnya.
Mitar
3

Bagaimana dengan skrip PHP? :)

Lihat sumber pada skrip ini dan Anda akan memiliki semua hak istimewa yang terdaftar:

//connect
mysql_select_db("mysql", mysql_connect("localhost","root",""));

//create grants select statements
$rs = mysql_query("SELECT DISTINCT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') AS query FROM user");

//iterate through grants
while ($row=mysql_fetch_array($rs)) {
    //run grant query
    $rs2 = mysql_query($row['query']);
    //iterate through results
    while($row2 = mysql_fetch_array($rs2)){
        //print results
        echo $row2[0] . ";\n\n";
    }
}
Ibrahim Lawal
sumber
2

buat file skrip shell dengan kode berikut:

############################################ 3
echo "SELECT DISTINCT CONCAT (\"show grants for '\", user, \"'@'\", host, \"';\") AS query FROM mysql.user; " >   script.sql    
echo "*** You will be asked to enter the root password twice ******"    
mysql -u root -p  < script.sql > output.sql ;    
cat output.sql | grep show > output1.sql  ; rm output.sql -f ; 
mysql -u root -p  < output1.sql > output.sql ;
clear
echo "-----Exported Grants-----"    
cat  output.sql ; rm  output.sql   output1.sql -f    
echo "-------------------------"
rm  script.sql -f
#

**** kemudian jalankan di shell seperti ini: Anda akan diminta untuk memasukkan kata sandi root dua kali dan kemudian GRANTS SQL akan ditampilkan di layar. ****


sumber
0

One-liner melakukan hampir sama dengan yang mengagumkan pt-show-grants:

mysql --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql --skip-column-names -A | sed 's/$/;/g'

Hanya berdasarkan alat unix, tidak ada perangkat lunak tambahan yang diperlukan.

Jalankan dari dalam bash shell, diasumsikan Anda memiliki fungsi di .my.cnfmana kata sandi mysql rootpengguna Anda dapat dibaca.

sja
sumber
Saya menggandakan setengah dari postingan @rolandomysqldba setelah kembali setengah tahun kemudian, saya baru sadar.
sjas