ฉันจะส่งออกสิทธิพิเศษจาก MySQL แล้วนำเข้าสู่เซิร์ฟเวอร์ใหม่ได้อย่างไร


88

ฉันรู้วิธีการส่งออก / นำเข้าฐานข้อมูลโดยใช้ mysqldump & ทำได้ดี แต่ฉันจะได้รับสิทธิพิเศษในเซิร์ฟเวอร์ใหม่ได้อย่างไร

สำหรับจุดพิเศษนั้นมีฐานข้อมูลอยู่สองสามตัวในฐานข้อมูลใหม่แล้วฉันจะนำเข้าสิทธิ์เซิร์ฟเวอร์เก่าโดยไม่ต้องทำสองวิธีที่มีอยู่

เซิร์ฟเวอร์เก่า: 5.0.67-community

เซิร์ฟเวอร์ใหม่: 5.0.51a-24 + lenny1

แก้ไข: ฉันมีการถ่ายโอนข้อมูลของ db 'mysql' จากเซิร์ฟเวอร์เก่าและตอนนี้ต้องการทราบวิธีที่เหมาะสมในการผสานกับ 'mysql' db บนเซิร์ฟเวอร์ใหม่

ฉันลอง 'นำเข้า' โดยตรงโดยใช้ phpMyAdmin และลงเอยด้วยข้อผิดพลาดเกี่ยวกับรายการซ้ำ (อันที่ฉันได้ทำการย้ายด้วยตนเองแล้ว)

ใครมีวิธีที่สวยงามในการรวมฐานข้อมูล 'mysql' สองอันเข้าด้วยกัน?


1. จำเป็นหรือไม่ที่คุณจะต้องใช้ PHPMyAdmin ถ้าเป็นฉันจะเขียนคำแนะนำเฉพาะสำหรับคุณบาง PHPMyAdmin 2. จาก PHPMyAdmin ถ้าคุณพยายามที่จะ "select * from mysql.user limit 1;" คุณได้รับผลลัพธ์หรือข้อผิดพลาด
Bruno Bronosky

1
ดังที่ฉันพูดถึงด้านล่างฉันคิดว่าสคริปต์ mygrants ของ Richard เป็นวิธีที่ดีในการรับข้อมูลการให้สิทธิ์ อย่างไรก็ตามคุณสามารถลองแก้ไขไฟล์ดัมพ์เพื่อใส่เครื่องหมายความคิดเห็น INSERT ในตารางผู้ใช้สำหรับผู้ใช้ที่มีอยู่แล้ว สิทธิ์สำหรับ dbs ที่เรียกคืนจากเซิร์ฟเวอร์เก่าจะถูกคัดลอก หากคุณได้กำหนดสิทธิพิเศษด้วยตนเองสำหรับบางส่วนของ dbs ที่คุณกู้คืนไปยังกล่องใหม่ให้ค้นหาชื่อตารางเหล่านี้ในไฟล์สิทธิ์และแสดงความคิดเห็นเหล่านี้ด้วย อย่าลืม flush_privileges ในภายหลัง คำอธิบายที่ดีของ mysql db ที่: grahamwideman.com/gw/tech/mysql/perms/index.htm
nedm

คำตอบ:


169

อย่ายุ่งกับ mysql db มีมากขึ้นเกิดขึ้นที่นั่นมากกว่าเพียงแค่ตารางผู้ใช้ ทางออกที่ดีที่สุดของคุณคือคำสั่ง" SHOW GRANTS FOR" ฉันมีนามแฝงและหน้าที่บำรุงรักษา CLI จำนวนมากใน. bashrc ของฉัน (อันที่จริงแล้วคือ. bash_aliases ของฉันซึ่งฉันได้รับมาใน. bashrc ของฉัน) ฟังก์ชั่นนี้:

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

คำสั่ง mysql แรกใช้ SQL เพื่อสร้าง SQL ที่ถูกต้องซึ่งถูกไพพ์ไปยังคำสั่ง mysql ที่สอง ผลลัพธ์จะถูกไพพ์ผ่าน sed เพื่อเพิ่มความคิดเห็นที่น่ารัก

$ @ ในคำสั่งจะอนุญาตให้คุณเรียกมันว่า: mygrants --host = prod-db1 --user = admin - password = secret

คุณสามารถใช้ชุดเครื่องมือ unix แบบเต็มของคุณในลักษณะเช่นนี้:

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

นั่นคือวิธีที่ถูกต้องในการเคลื่อนย้ายผู้ใช้ MySQL ACL ของคุณได้รับการแก้ไขด้วย SQL บริสุทธิ์


นี่เป็นฟังก์ชั่นผู้ช่วยทุบตีที่ดีมาก รับเอาต์พุตจากนั้นและสามารถเรียกใช้บนเซิร์ฟเวอร์ใหม่และสิทธิพิเศษจะถูกป้อนอย่างถูกต้องและแม่นยำ
Jeremy Bouse

1
ฉันรักฟังก์ชั่นของคุณวันนี้มันช่วยฉันทำงานได้มากมาย ขอบคุณขอบคุณขอบคุณ ...
Fabio

2
นี่ยอดเยี่ยม แต่มีข้อบกพร่องใหญ่อย่างหนึ่ง มีการเพิ่ม "\" พิเศษเพื่อขีดล่างในชื่อฐานข้อมูลดังนั้นหากคุณมีตัวอย่างผู้ใช้ที่มีสิทธิ์เฉพาะในฐานข้อมูลที่เรียกว่า foo_bar มันจะถูกแสดงผลเป็น foo \ _bar แทน foo_bar ดังนั้นจะไม่ถูกนำเข้าอย่างถูกต้อง . อย่างน้อยที่สุดสิ่งนี้จะเกิดขึ้นหากคุณบันทึกผลลัพธ์จากสคริปต์ของคุณลงในไฟล์ SQL แล้วนำเข้าสู่เซิร์ฟเวอร์ใหม่ ฉันไม่ได้ลองส่งออกและนำเข้าท่อโดยตรงในบรรทัดเดียว
matteo

1
ระวังด้วยคำสั่งนี้ หากคุณมีในuserตารางผู้ใช้ที่มีโฮสต์%แต่จากนั้นในdbตารางที่คุณมีรายการที่hostมีค่าที่ชัดเจนรายการเหล่านั้นในdbตารางจะไม่ถูกเรียกคืนโดยใช้วิธีนี้
Mitar

1
@matteo เพิ่ม-rคำสั่ง MySQL 2 mysqlในฟังก์ชั่นและหนีคู่จะไม่ถูกส่งออกโดย เช่น:mysql -r $@
lifo

45

มีสองวิธีในการแยก SQL Grants ออกจากอินสแตนซ์ MySQL

วิธี # 1

คุณสามารถใช้pt-show-grants ได้จาก Percona Toolkit

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

วิธีที่ # 2

คุณสามารถจำลองได้pt-show-grantsดังต่อไปนี้

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

วิธีใดวิธีหนึ่งจะสร้างการถ่ายโอนข้อมูล SQL แท้ของ MySQL มอบให้ สิ่งที่เหลืออยู่ที่ต้องทำคือเรียกใช้สคริปต์บนเซิร์ฟเวอร์ใหม่:

mysql -uroot -p -A < MySQLUserGrants.sql

ให้มันลอง !!!


1
pt-show-grants เป็นสิ่งที่คุณต้องการสำหรับสิ่งนี้มันใช้งานได้ดี
Glenn Plas

เพอร์โคนาเป็นสุดยอดความบริสุทธิ์
sjas

7
แต่คำตอบ # 2 นั้นดีและจะทำงานได้โดยไม่มีซอฟต์แวร์เพิ่มเติม!
sjas

14

คำตอบของ Richard Bronosky นั้นมีประโยชน์มากสำหรับฉัน ขอบคุณมาก!!!

นี่คือรูปแบบขนาดเล็กซึ่งมีประโยชน์สำหรับฉัน มันจะมีประโยชน์สำหรับการถ่ายโอนผู้ใช้เช่นระหว่างสองการติดตั้ง Ubuntu ที่ใช้ phpmyadmin เพียงแค่ถ่ายโอนสิทธิ์สำหรับผู้ใช้ทั้งหมดนอกเหนือจากรูท phpmyadmin และ debian-sys-maint รหัสนั้น

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
หากคุณดูตัวอย่างของฉันที่ฉันgrep rails_adminสามารถอนุมานวิธีการทำเช่นนี้ได้โดยไม่ต้องทำฟังก์ชั่นพิเศษสำหรับเคสแบบขอบทุกอัน ใช้ตัวเลือก "invert-match" ของ grep ดังนี้: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

หรือใช้ percona-toolkit (maatkit เดิม) และใช้pt-show-grants(หรือmk-show-grants) เพื่อจุดประสงค์นั้น ไม่จำเป็นต้องใช้สคริปต์ที่ยุ่งยากและ / หรือขั้นตอนการจัดเก็บ


5

คุณสามารถ mysqldump ฐานข้อมูล 'mysql' และนำเข้าไปยังฐานข้อมูลใหม่ จะต้องใช้ flush_privileges หรือรีสตาร์ทและคุณจะต้องสำรองฐานข้อมูล mysq ที่มีอยู่ก่อน

เพื่อหลีกเลี่ยงการลบสิทธิ์ที่มีอยู่ของคุณตรวจสอบให้แน่ใจว่าได้ผนวกมากกว่าแทนที่แถวในตารางสิทธิ์ (db, columns_priv, โฮสต์, func ฯลฯ )


ขอบคุณ @nedm ดูเหมือนว่าเซิร์ฟเวอร์ cPanel ที่น่ารำคาญฉันพยายามดึง dbs ออกไม่แสดง db 'mysql' มิฉะนั้นฉันจะทดสอบและยืนยันคำตอบของคุณ เมื่อฉันรู้ว่าฉันจะกลับมาตรวจสอบ ขอบคุณ
Gareth

ที่โชคร้าย แต่เข้าใจได้คุณอาจถูกป้องกันไม่ให้เข้าถึงฐานข้อมูลใด ๆ แต่เป็นฐานข้อมูลที่ผู้ใช้ของคุณเป็นเจ้าของโดยตรงบน db ที่ใช้ร่วมกัน
Dave Cheney

โอ้ใช่โดยไม่ต้องเข้าถึง 'mysql' มันจะเป็นการยากที่จะทำสิ่งที่เกี่ยวข้องกับผู้ใช้หรือการอนุญาต คุณมีการเข้าถึงบรรทัดคำสั่งหรือไม่ คุณสามารถรัน mysqldump จากเทอร์มินัลหรือบรรทัดคำสั่ง (ไม่ใช่จากเชลล์ mysql) ได้หรือไม่? mysqldump -u ชื่อผู้ใช้ -ppassword mysql> mysqldump.sql
nedm

db 'mysql' นั้นสามารถเข้าถึงได้จาก Cpanel WHM หากฉันเข้าสู่ระบบในฐานะ 'root' จากนั้นฉันสามารถเข้าถึงรุ่นของ phpMyAdmin ซึ่งมีฐานข้อมูลที่มีสิทธิ์ 'MySQL'
แกเร็ ธ

ผสานเข้ากับสคีมา mysql ที่มีอยู่แล้วข้อมูลที่ดึงมาจากสคีมา mysql ผ่านทาง mysqldump นั้นเกือบจะแน่นอนว่าเป็นปัญหา คุณกำลังจัดการกับ schema ที่ซับซ้อนด้วยความสัมพันธ์ที่ถูกบังคับใช้ ฯลฯ schema นี้มีความซับซ้อนจริง ๆ แล้วพวกเขาสร้างไวยากรณ์ SQL เฉพาะ (GRANT, REVOKE, DROP USER และอื่น ๆ ) เพื่อจัดการกับมัน อย่างไรก็ตามแยกของคุณประกอบด้วยคำสั่ง INSERT เท่านั้น ฉันไม่มีตัวละครเหลือเลย ฉันต้องการดำเนินการต่อหรือไม่
Bruno Bronosky

4

คุณสามารถทำตามขั้นตอนที่เก็บไว้ได้:

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

และเรียกมันด้วย

$ mysql -p -e "CALL spShowGrants" mysql

จากนั้นไพพ์เอาต์พุตผ่านคำสั่ง Richards sed เพื่อรับการสำรองข้อมูลสิทธิพิเศษ


3

แม้ว่าคำตอบของ @Richard Bronosky จะเป็นคำตอบที่ถูกต้อง แต่ฉันก็ได้พบกับคำถามนี้หลังจากพยายามย้ายฐานข้อมูลชุดหนึ่งจากเซิร์ฟเวอร์หนึ่งไปยังอีกเซิร์ฟเวอร์หนึ่งและวิธีการแก้ปัญหานั้นง่ายกว่ามาก:

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

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

ณ จุดนี้ข้อมูลทั้งหมดของฉันมองเห็นถ้าฉันเข้าสู่ระบบเป็นrootที่mysql.userตารางมีทุกอย่างในนั้นผมคาดหวัง แต่ฉันไม่สามารถเข้าสู่ระบบในฐานะใด ๆ ของผู้ใช้อื่น ๆ และพบว่าคำถามนี้สมมติว่าฉันต้องอีกครั้ง ออกGRANTคำสั่ง

อย่างไรก็ตามปรากฎว่าเซิร์ฟเวอร์ mysql จำเป็นต้องเริ่มต้นใหม่เพื่อให้ได้รับสิทธิ์ที่ปรับปรุงแล้วในmysql.*ตารางเพื่อให้มีผล:

server2$ sudo restart mysql

หวังว่าจะช่วยให้คนอื่นบรรลุสิ่งที่ควรจะเป็นงานง่าย!


โอ้และสถานการณ์ของฉันแตกต่างจาก OP เล็กน้อยนั่นคือฉันไม่ได้พยายามรวมการถ่ายโอนข้อมูลเข้ากับเซิร์ฟเวอร์ที่มีฐานข้อมูล / ผู้ใช้อยู่
ทอม

2
คุณไม่จำเป็นต้องรีสตาร์ท MySQLd เพื่อ 'อัพเดทสิทธิ์' มันสามารถทำได้ด้วยคำสั่ง MySQL 'ล้างสิทธิ์'
CloudWeavers

ปัญหาของวิธีนี้คือมันทำงานได้ก็ต่อเมื่อทั้ง MySQL ต้นทางและปลายทางรุ่นเดียวกัน มิฉะนั้นคุณอาจมีปัญหาเนื่องจากตาราง mysql.user มีคอลัมน์ที่แตกต่างจากตารางปลายทาง mysql.user
Mitar

3

สคริปต์ PHP เป็นอย่างไร? :)

ดูที่มาของสคริปต์นี้และคุณจะได้รับสิทธิ์ทั้งหมดในรายการ:

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

สร้างเชลล์สคริปต์ไฟล์ด้วยรหัสต่อไปนี้:

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

**** จากนั้นเรียกใช้บนเชลล์เช่นนี้: คุณจะถูกขอให้ป้อนรหัสผ่านรูทสองครั้งจากนั้น GRANTS SQL จะปรากฏบนหน้าจอ ****


0

สายการบินเดียวที่ทำออกมาได้อย่างยอดเยี่ยมมาก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'

ขึ้นอยู่กับเครื่องมือ unix เท่านั้นไม่จำเป็นต้องใช้ซอฟต์แวร์เพิ่มเติม

ดำเนินการจากภายใน bash shell สมมติว่าคุณมีการทำงาน.my.cnfที่รหัสผ่านของmysql rootผู้ใช้ของคุณสามารถอ่านได้


ฉันทำสำเนาครึ่งหนึ่งของโพสต์ของ @rolandomysqldba หลังจากกลับมาครึ่งปีต่อมาฉันเพิ่งรู้
sjas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.