Làm cách nào tôi có thể xuất các đặc quyền từ MySQL và sau đó nhập vào máy chủ mới?


88

Tôi biết cách xuất / nhập cơ sở dữ liệu bằng mysqldump và điều đó tốt nhưng làm cách nào tôi có được các đặc quyền vào máy chủ mới.

Đối với các điểm bổ sung, đã có một vài cơ sở dữ liệu hiện có trên cơ sở dữ liệu mới, làm cách nào để nhập các đặc quyền máy chủ cũ mà không cần loại bỏ các cặp cơ sở dữ liệu hiện có.

Máy chủ cũ: 5.0,67-cộng đồng

Máy chủ mới: 5.0.51a-24 + lenny1

EDIT: Tôi đã nhận được một db 'mysql' từ Máy chủ cũ và bây giờ muốn biết cách hợp nhất với db 'mysql' trên Máy chủ mới.

Tôi đã thử 'Nhập' bằng cách sử dụng phpMyAdmin và đã gặp lỗi liên quan đến bản sao (một lỗi mà tôi đã di chuyển thủ công).

Bất cứ ai cũng có một cách hợp nhất để hợp nhất hai cơ sở dữ liệu 'mysql'?


1. Đây có phải là một yêu cầu để bạn sử dụng PHPMyAdmin không? Nếu đó là tôi sẽ viết một số hướng dẫn cụ thể về PHPMyAdmin cho bạn. 2. Từ PHPMyAdmin nếu bạn cố gắng "chọn * từ mysql.user giới hạn 1;" Bạn có nhận được kết quả hoặc một lỗi.
Bruno Bronosky

1
Như tôi đã đề cập dưới đây, tôi nghĩ kịch bản mygrant của Richard là một cách tốt để có được thông tin tài trợ. Tuy nhiên, bạn cũng có thể thử chỉnh sửa tệp kết xuất để nhận xét INSERT cho bảng người dùng cho người dùng đã tồn tại. Các đặc quyền cho các dbs được khôi phục từ máy chủ cũ sau đó sẽ được sao chép. Nếu bạn đã gán đặc quyền theo cách thủ công cho một số dbs bạn đã khôi phục vào hộp mới, hãy tìm các tên bảng này trong các tệp đặc quyền và cũng nhận xét chúng. Đừng quên một fl_prives sau đó. Mô tả hay về db ​​mysql tại: grahamwideman.com/gw/tech/mysql/perms/index.htm
nedm

Câu trả lời:


169

Đừng lộn xộn với db mysql. Có rất nhiều thứ đang diễn ra ở đó hơn là chỉ bảng người dùng. Đặt cược tốt nhất của bạn là lệnh " SHOW GRANTS FOR". Tôi có rất nhiều bí danh và hàm bảo trì CLI trong .bashrc của tôi (thực ra là .bash_aliases mà tôi cung cấp trong .bashrc của mình). Chức năng này:

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

Lệnh mysql đầu tiên sử dụng SQL để tạo SQL hợp lệ được chuyển sang lệnh mysql thứ hai. Đầu ra sau đó được dẫn qua sed để thêm bình luận đẹp.

$ @ Trong lệnh sẽ cho phép bạn gọi nó là: mygrant --host = prod-db1 --user = admin --password = secret

Bạn có thể sử dụng bộ công cụ unix đầy đủ của mình như thế này:

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

Đó là cách đúng đắn để di chuyển người dùng. MySQL ACL của bạn được sửa đổi với SQL thuần túy.


Đây thực sự là một chức năng trợ giúp bash tốt đẹp hoạt động tuyệt vời. Lấy đầu ra từ đó và có thể chạy trên máy chủ mới và các đặc quyền sẽ được nhập chính xác và chính xác.
Jeremy Bouse

1
Tôi yêu chức năng của bạn, hôm nay nó đã tiết kiệm cho tôi rất nhiều công việc. Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn ...
Fabio

2
Điều này là tuyệt vời nhưng nó có một lỗ hổng lớn. Một "\" bổ sung được thêm vào dấu gạch dưới trong tên cơ sở dữ liệu, vì vậy, nếu bạn có một người dùng có đặc quyền cụ thể trên cơ sở dữ liệu có tên foo_bar, thì nó sẽ được hiển thị dưới dạng foo \ _bar thay vì foo_bar, do đó sẽ không được nhập chính xác . Ít nhất, điều này xảy ra nếu bạn lưu đầu ra từ tập lệnh của bạn vào tệp SQL và sau đó nhập nó vào máy chủ mới. Tôi đã không thử đường ống xuất và nhập trực tiếp trong một dòng.
matteo

1
Hãy cẩn thận với lệnh này. Nếu bạn có trong userbảng một người dùng có máy chủ lưu trữ %, nhưng sau đó trong dbbảng bạn có các mục nhập có hostgiá trị rõ ràng, các mục trong dbbảng không được truy xuất bằng phương thức này.
Mitar

1
@matteo Thêm vào -rlệnh mysql thứ 2 trong hàm và các lối thoát kép sẽ không được xuất ra bởi mysql. ví dụ:mysql -r $@
lifo

45

Có hai phương pháp để trích xuất Tài trợ SQL từ Trường hợp MySQL

PHƯƠNG PHÁP # 1

Bạn có thể sử dụng pt-show- Grant từ Percona Toolkit

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

PHƯƠNG PHÁP # 2

Bạn có thể mô phỏng pt-show-grantsvới những điều sau đây

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

Một trong hai phương thức sẽ tạo ra một kết xuất SQL thuần túy của các khoản tài trợ MySQL. Tất cả những gì còn lại phải làm là thực thi tập lệnh trên một máy chủ mới:

mysql -uroot -p -A < MySQLUserGrants.sql

Hãy thử một lần !!!


1
pt-show-Grants chính xác là những gì bạn muốn cho việc này, nó hoạt động rất tốt.
Glenn Plas

Percona chỉ là sự tuyệt vời thuần túy.
sjas

7
Nhưng câu trả lời số 2 cũng tốt như vậy và sẽ hoạt động mà không cần phần mềm bổ sung!
sjas

14

Câu trả lời của Richard Bronosky cực kỳ hữu ích cho tôi. Cảm ơn nhiều!!!

Đây là một biến thể nhỏ hữu ích cho tôi. Nó rất hữu ích cho việc chuyển người dùng, ví dụ giữa hai bản cài đặt Ubuntu chạy phpmyadmin. Chỉ cần bỏ các đặc quyền cho tất cả người dùng ngoài root, phpmyadmin và debian-sys-notify. Mã là sau đó

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

2
Nếu bạn nhìn vào ví dụ của tôi, nơi tôi grep rails_admincó thể suy ra cách thực hiện điều này mà không cần thực hiện một chức năng đặc biệt cho mọi trường hợp cạnh. Sử dụng tùy chọn "đảo ngược" của grep như vậy: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

Hoặc, sử dụng percona-toolkit (maatkit cũ) và sử dụng pt-show-grants(hoặc mk-show-grants) cho mục đích đó. Không cần các kịch bản rườm rà và / hoặc các thủ tục được lưu trữ.


5

Bạn có thể mysqldump cơ sở dữ liệu 'mysql' và nhập vào cơ sở dữ liệu mới; một yêu cầu hoặc khởi động lại sẽ được yêu cầu và chắc chắn bạn sẽ muốn sao lưu mysq db hiện tại trước tiên.

Để tránh loại bỏ các đặc quyền hiện có của bạn, hãy đảm bảo nối thêm thay vì thay thế các hàng trong các bảng đặc quyền (db, Cột_priv, máy chủ lưu trữ, func, v.v.).


Cảm ơn @nedm. Có vẻ như máy chủ cPanel phiền phức Tôi đang cố gắng tắt dbs không hiển thị db 'mysql'. Nếu không, tôi sẽ kiểm tra và khẳng định câu trả lời của bạn. Khi tôi nhận ra rằng tôi sẽ kiểm tra lại. Cảm ơn.
Gareth

Điều đó thật đáng tiếc nhưng có thể hiểu được, có lẽ bạn bị ngăn truy cập vào bất kỳ cơ sở dữ liệu nào ngoại trừ những cơ sở dữ liệu do người dùng của bạn trực tiếp sở hữu trên một db được chia sẻ.
Dave Cheney

Ouch, yeah, không có quyền truy cập vào 'mysql', sẽ khó có thể làm bất cứ điều gì liên quan đến người dùng hoặc quyền. Bạn có quyền truy cập dòng lệnh? Bạn có thể chạy mysqldump từ thiết bị đầu cuối hoặc dòng lệnh (KHÔNG phải từ shell mysql) không? mysqldump -u tên người dùng -ppassword mysql> mysqldump.sql
nedm

Db 'mysql' có thể truy cập được từ Cpanel WHM nếu tôi đăng nhập với tư cách là 'root'. Từ đó tôi có thể truy cập một phiên bản phpmyadmin có cơ sở dữ liệu 'mysql' có quyền
Gareth

Hợp nhất vào một lược đồ mysql hiện có, dữ liệu được trích xuất từ ​​một lược đồ mysql thông qua mysqldump gần như chắc chắn là có vấn đề. Bạn đang thao tác một lược đồ phức tạp với các mối quan hệ được thi hành, v.v ... Lược đồ này rất phức tạp, trên thực tế, họ đã tạo ra cú pháp SQL chuyên dụng (GRANT, REVOKE, DROP USER, v.v.) để xử lý nó. Trích xuất của bạn, tuy nhiên, chỉ bao gồm các câu lệnh INSERT. Tôi đang hết nhân vật ở đây. Cần tôi tiếp tục?
Bruno Bronosky

4

Bạn cũng có thể làm điều đó như một thủ tục được lưu trữ:

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

và gọi nó với

$ mysql -p -e "CALL spShowGrants" mysql

sau đó dẫn đầu ra thông qua lệnh Richards sed để có bản sao lưu các đặc quyền.


3

Mặc dù câu trả lời của @Richard Bronosky là câu trả lời đúng, tôi đã gặp câu hỏi này sau khi cố gắng di chuyển một bộ cơ sở dữ liệu từ máy chủ này sang máy chủ khác và giải pháp đơn giản hơn nhiều:

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

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

Tại thời điểm này, tất cả dữ liệu của tôi đều hiển thị nếu tôi đăng nhập root, mysql.userbảng có mọi thứ tôi mong đợi, nhưng tôi không thể đăng nhập như bất kỳ người dùng nào khác và thấy câu hỏi này giả sử tôi phải đăng lại ban hành các GRANTtuyên bố.

Tuy nhiên, hóa ra máy chủ mysql chỉ cần được khởi động lại để các đặc quyền được cập nhật trong các mysql.*bảng có hiệu lực:

server2$ sudo restart mysql

Hy vọng rằng sẽ giúp người khác đạt được những gì nên là một nhiệm vụ đơn giản!


Ồ, và hoàn cảnh của tôi hơi khác với OP, ở chỗ tôi không cố gắng hợp nhất một bãi chứa vào một máy chủ với cơ sở dữ liệu / người dùng hiện có.
Tom

2
Bạn thực sự không phải khởi động lại MySQLd để 'cập nhật các đặc quyền'. Nó có thể được thực hiện với lệnh MySQL 'flush đặc quyền;'
CloudWeavers

Vấn đề với cách tiếp cận này là nó chỉ hoạt động khi cả phiên bản MySQL nguồn và đích đều giống nhau. Nếu không, bạn có thể gặp sự cố vì bảng mysql.user nguồn có các cột khác với bảng mysql.user đích chẳng hạn.
Mitar

3

Làm thế nào về một kịch bản PHP? :)

Xem nguồn trên tập lệnh này và bạn sẽ có tất cả các đặc quyền được liệt kê:

//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";
    }
}

2

tạo tập tin shell shell với đoạn mã sau:

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

**** sau đó chạy nó trên shell như thế này: bạn sẽ được yêu cầu nhập mật khẩu gốc hai lần và sau đó SQL GRANTS sẽ được hiển thị trên màn hình. ****


0

One-liner làm khá nhiều thứ giống như tuyệt vời 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'

Chỉ dựa trên các công cụ unix, không cần phần mềm bổ sung.

Thực thi từ bên trong bash shell, giả sử là bạn đang làm việc .my.cnftrong đó mật khẩu của mysql rootngười dùng của bạn có thể được đọc.


Tôi đã nhân đôi một nửa bài đăng của @rolandomysqldba sau khi trở lại nửa năm sau, tôi mới nhận ra.
sjas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.