Jak mogę wyeksportować uprawnienia z MySQL, a następnie zaimportować na nowy serwer?

88

Wiem, jak eksportować / importować bazy danych przy użyciu mysqldump i to dobrze, ale jak uzyskać uprawnienia na nowym serwerze.

Aby uzyskać dodatkowe punkty, istnieje już kilka istniejących baz danych na nowym, jak zaimportować stare uprawnienia do serwerów bez konieczności eliminowania kilku istniejących.

Stary serwer: 5.0.67-społeczność

Nowy serwer: 5.0.51a-24 + lenny1

EDYCJA: Mam zrzut db 'mysql' ze Starego Serwera i teraz chcę poznać właściwy sposób połączenia z db 'mysql' na Nowym Serwerze.

Próbowałem prostego „importowania” przy użyciu phpMyAdmin i zakończyłem się błędem dotyczącym duplikatu (takiego, który już migrowałem ręcznie).

Czy ktoś ma elegancki sposób na połączenie dwóch baz danych „mysql”?

Gareth
źródło
1. Czy korzystanie z PHPMyAdmin jest wymagane? Jeśli tak, napiszę dla ciebie instrukcje specyficzne dla PHPMyAdmin. 2. W PHPMyAdmin, jeśli spróbujesz „wybrać * z mysql.user limit 1;” otrzymujesz wyniki lub błąd.
Bruno Bronosky
1
Jak wspomniałem poniżej, myślę, że skrypt mygrantów Richarda jest dobrym sposobem na uzyskanie informacji o grantach. Możesz także spróbować edytować plik zrzutu, aby skomentować INSERT w tabeli użytkowników dla użytkowników, którzy już istnieją. Przywileje przywracane ze starego serwera dbs zostaną skopiowane. Jeśli ręcznie przypisałeś uprawnienia do niektórych przywracanych dbs do nowego pola, poszukaj nazw tabel w plikach uprawnień i również je skomentuj. Nie zapomnij później o flush_privileges. Dobry opis bazy
nedm

Odpowiedzi:

169

Nie zadzieraj z db mysql. Tam dzieje się o wiele więcej niż tylko tabela użytkowników. Najlepszym rozwiązaniem jest polecenie „ POKAŻ DOTACJE ”. Mam wiele aliasów i funkcji konserwacyjnych CLI w moim .bashrc (właściwie moje .bash_aliases, które pozyskuję w moim .bashrc). Ta funkcja:

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;}'
}

Pierwsza komenda mysql używa SQL do generowania poprawnego SQL, który jest przesyłany potokowo do drugiej komendy mysql. Dane wyjściowe są następnie przesyłane strumieniowo przez sed, aby dodać ładne komentarze.

$ @ W ​​poleceniu pozwoli ci nazywać go jako: mygrants --host = prod-db1 --user = admin --password = secret

Możesz użyć pełnego zestawu narzędzi unixowych w następujący sposób:

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

To jest właściwy sposób na przenoszenie użytkowników. Twoja lista ACL MySQL jest modyfikowana czystym SQL.

Bruno Bronosky
źródło
To naprawdę fajna funkcja pomocnika bash, która działa świetnie. Po uzyskaniu danych wyjściowych można uruchomić nowy serwer, a uprawnienia zostaną wprowadzone poprawnie i dokładnie.
Jeremy Bouse
1
Uwielbiam twoją funkcję, dziś zaoszczędziło mi to dużo pracy. Dziękuję, dziękuję, dziękuję ...
Fabio
2
To świetnie, ale ma jedną wielką wadę. Dodatkowe podkreślenie „\” jest dodawane do znaków podkreślenia w nazwach baz danych, więc jeśli masz na przykład użytkownika z określonymi uprawnieniami w bazie danych o nazwie foo_bar, będzie on renderowany jako foo \ _bar zamiast foo_bar, więc nie zostanie poprawnie zaimportowany . Przynajmniej dzieje się tak, jeśli zapiszesz wynik skryptu w pliku SQL, a następnie zaimportujesz go na nowy serwer. Nie próbowałem bezpośredniego potoku eksportu i importu w jednym wierszu.
matteo
1
Uważaj na to polecenie. Jeśli masz w usertabeli użytkownika z hostem %, ale następnie w dbtabeli masz wpisy, w których hostjest wyraźna wartość, te wpisy w dbtabeli nie są pobierane przy użyciu tej metody.
Mitar
1
@matteo Dodaj -rdo drugiej komendy mysql w funkcji, a podwójne znaki specjalne nie będą generowane przez mysql. np .:mysql -r $@
lifo
45

Istnieją dwie metody wyodrębniania Grants SQL z wystąpienia MySQL

METODA nr 1

Możesz skorzystać z pt-show- grants z Percona Toolkit

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

SPOSÓB 2

Możesz emulować pt-show-grantsw następujący sposób

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

Każda z metod wygeneruje czysty zrzut SQL dotacji MySQL. Pozostaje tylko wykonać skrypt na nowym serwerze:

mysql -uroot -p -A < MySQLUserGrants.sql

Spróbuj !!!

RolandoMySQLDBA
źródło
1
pt-show-grants jest dokładnie tym, czego chcesz, działa świetnie.
Glenn Plas,
Perkona jest po prostu niesamowitą grą.
sjas
7
Ale odpowiedź # 2 jest równie dobra i zadziała bez dodatkowego oprogramowania!
sjas
14

Odpowiedź Richarda Bronoskiego była dla mnie niezwykle przydatna. Wielkie dzięki!!!

Oto mała odmiana, która była dla mnie przydatna. Jest to przydatne do przenoszenia użytkowników np. Między dwiema instalacjami Ubuntu z uruchomionym phpmyadmin. Po prostu zrzuć uprawnienia dla wszystkich użytkowników oprócz root, phpmyadmin i debian-sys-maint. Kod jest wtedy

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
źródło
2
Jeśli spojrzysz na mój przykład, w którym mogę grep rails_adminwywnioskować, jak to zrobić, nie tworząc specjalnej funkcji dla każdego przypadku krawędzi. Użyj opcji „odwracania” mygrants --host=prod-db1 --user=admin --password=secret | grep -Ev 'root|phpmyadmin|debian-sys-maint' | mysql --host=staging-db1 --user=admin --password=secret
grepa w następujący
7

Lub użyj percona-toolkit (dawniej maatkit) i użyj pt-show-grants(lub mk-show-grants) do tego celu. Nie potrzeba uciążliwych skryptów i / lub procedur przechowywanych.

MrkiMile
źródło
5

Możesz wykonać mysqldump bazę danych „mysql” i zaimportować ją do nowej; wymagane będą flush_privileges lub restart i na pewno będziesz chciał najpierw wykonać kopię zapasową istniejącej bazy danych mysq.

Aby uniknąć usuwania istniejących uprawnień, pamiętaj o dodawaniu wierszy w tabelach uprawnień (db, column_priv, host, func itp.).

nedm
źródło
Dzięki @nedm. Wydaje się, że denerwujący serwer cPanel, który próbuję wyłączyć, nie pokazuje db 'mysql'. W przeciwnym razie przetestuję i potwierdzę twoją odpowiedź. Kiedy to zrozumiem, sprawdzę ponownie. Dzięki.
Gareth
To niefortunne, ale zrozumiałe, prawdopodobnie nie masz dostępu do żadnej bazy danych oprócz tych, które są bezpośrednio własnością twojego użytkownika na wspólnej bazie danych.
Dave Cheney
O tak, bez dostępu do „mysql” trudno będzie zrobić cokolwiek związanego z użytkownikami lub uprawnieniami. Czy masz dostęp do wiersza poleceń? Czy możesz uruchomić mysqldump z terminala lub wiersza poleceń (NIE z powłoki mysql)? mysqldump -u nazwa użytkownika -hasło mysql> mysqldump.sql
nedm
Db „mysql” był dostępny z Cpanel WHM, jeśli zalogowałem się jako „root”. Stamtąd mogę uzyskać dostęp do wersji phpmyadmin, która ma bazę danych „mysql” zawierającą uprawnienia
Gareth
Po scaleniu z istniejącym schematem mysql dane wyodrębnione ze schematu mysql za pomocą mysqldump prawie na pewno będą problematyczne. Manipulujesz złożonym schematem za pomocą wymuszonych relacji itp. Ten schemat jest tak skomplikowany, że stworzyli dedykowaną składnię SQL (GRANT, REVOKE, DROP USER itp.), Aby sobie z tym poradzić. Twój wyciąg składa się jednak tylko z instrukcji INSERT. Zabrakło mi tutaj postaci. Czy muszę kontynuować?
Bruno Bronosky,
4

Możesz to również zrobić jako procedurę przechowywaną:

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

i zadzwoń za pomocą

$ mysql -p -e "CALL spShowGrants" mysql

następnie potokuj dane wyjściowe za pomocą polecenia Richards sed, aby uzyskać kopię zapasową uprawnień.

Lenny
źródło
3

Chociaż wydaje się, że @Richard Bronosky jest poprawną odpowiedzią, natknąłem się na to pytanie po próbie migracji zestawu baz danych z jednego serwera na drugi, a rozwiązanie było znacznie prostsze:

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

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

W tym momencie wszystkie moje dane były widoczne, gdy się zalogowałem root, ponieważ mysql.usertabela zawierała wszystko, czego się spodziewałem, ale nie mogłem zalogować się jako żaden inny użytkownik i znalazłem to pytanie, zakładając, że muszę ponownie wystawić GRANToświadczenia.

Okazuje się jednak, że serwer mysql po prostu musiał zostać zrestartowany, aby zaktualizowane uprawnienia w mysql.*tabelach zaczęły obowiązywać:

server2$ sudo restart mysql

Mam nadzieję, że pomoże to komuś innemu osiągnąć to, co powinno być prostym zadaniem!

Tomek
źródło
Aha, a moja sytuacja nieco różniła się od OP, ponieważ nie próbowałem scalić zrzutu do serwera z istniejącymi bazami danych / użytkownikami.
Tom
2
Nie trzeba zrestartować MySQLd, aby „zaktualizować uprawnienia”. Można to zrobić za pomocą polecenia MySQL „uprawnienia do opróżniania;”
CloudWeavers
Problem z tym podejściem polega na tym, że działa ono tylko wtedy, gdy źródłowa i docelowa wersja MySQL jest taka sama. W przeciwnym razie mogą wystąpić problemy, ponieważ na przykład źródłowa tabela mysql.user ma inne kolumny niż docelowa tabela mysql.user.
Mitar
3

Co powiesz na skrypt PHP? :)

Zobacz źródło tego skryptu, a będziesz mieć wszystkie wymienione uprawnienia:

//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
źródło
2

utwórz plik skryptu powłoki z następującym kodem:

################################################################################### 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
#

**** następnie uruchom go w powłoce w ten sposób: zostaniesz poproszony o podanie hasła roota dwa razy, a następnie GRANTS SQL zostanie wyświetlony na ekranie. ****


źródło
0

One-liner robi prawie to samo, co niesamowite 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'

Oparty tylko na narzędziach unixowych, nie jest potrzebne dodatkowe oprogramowanie.

Wykonaj z poziomu powłoki bash, zakładając, że masz działający system, w .my.cnfktórym mysql rootmożna odczytać hasło użytkownika.

sjas
źródło
zduplikowałem połowę posta @rolandomysqldba po powrocie pół roku później, właśnie sobie uświadomiłem.
sjas 13.04.16