ฉันสามารถคืนค่าตารางเดียวจากไฟล์ mysql แบบเต็ม mysqldump ได้หรือไม่


194

ฉันมีการสำรองข้อมูล mysqldump ของฐานข้อมูล mysql ของฉันซึ่งประกอบด้วยตารางทั้งหมดของเราซึ่งมีประมาณ 440 megs ฉันต้องการคืนค่าเนื้อหาของหนึ่งในตารางจาก mysqldump เป็นไปได้ไหม ในทางทฤษฎีฉันสามารถตัดส่วนที่สร้างตารางที่ฉันต้องการออกใหม่ แต่ฉันไม่รู้ด้วยซ้ำถึงวิธีแก้ไขเอกสารข้อความที่มีขนาดอย่างมีประสิทธิภาพ


2
FWIW คุณสามารถใช้mydumperได้ สิ่งนี้สร้างการถ่ายโอนข้อมูลแบบลอจิคัลเช่น mysqldump แต่จะแยกไฟล์ออกเป็นตารางต่อตารางและสามารถทำได้ทั้งการถ่ายโอนข้อมูลและการโหลดมัลติเธรดดังนั้นจึงใช้เวลาน้อยลง
Bill Karwin

คำตอบ:


290

คุณสามารถลองใช้ sed เพื่อแยกเฉพาะตารางที่คุณต้องการ

สมมติว่าชื่อตารางของคุณเป็นmytableไฟล์และไฟล์ mysql.dump เป็นไฟล์ที่มีดัมพ์ขนาดใหญ่ของคุณ:

$ sed -n -e '/CREATE TABLE.*`mytable`/,/CREATE TABLE/p' mysql.dump > mytable.dump

นี่จะเป็นการคัดลอกไฟล์mytable.dumpที่อยู่ระหว่างCREATE TABLE mytableและถัดไปที่CREATE TABLEเกี่ยวข้องกับตารางถัดไป

จากนั้นคุณสามารถปรับไฟล์mytable.dumpที่มีโครงสร้างของตารางmytableและข้อมูล (รายการINSERT)


5
นั่นก็ดีกว่าคำตอบของฉันเพราะมันดูแล CREATE TABLE เช่นกัน แต่คุณควรค้นหาด้วย backquotes เพื่อไม่ให้ได้ตารางอื่นที่เรียกว่า "thisismytabletoo"
JCCyC

1
จริง ฉันไม่แน่ใจว่าชื่อตารางในทิ้ง mysql ทั้งหมดถูกล้อมรอบด้วย backquote หรือถ้า "สร้างตาราง mytable" ก็อาจเป็นไปได้ เราสามารถปรับค่า regexp แรกได้อย่างง่ายดายหากเรารู้ว่าดัมพ์มีลักษณะอย่างไร ปัญหาที่สองอาจเป็นได้หากตาราง mytable ไม่ซ้ำกัน (หนึ่งในฐานข้อมูล db1 และอีกหนึ่งในฐานข้อมูล db2) ทั้งสองจะถูกส่งออกในไฟล์ mytable.dump หากตารางไม่ซ้ำกันเราสามารถใช้คำสั่ง sed เดียวกันก่อนด้วย CREATE DATABASE เพื่อแยกเฉพาะฐานข้อมูลที่ถูกต้อง จากนั้นใช้คำสั่ง sed ด้วย CREATE TABLE
uloBasEI

13
หวาน! อย่าลืมเพิ่มตาราง DROP ที่ด้านบนและลบตาราง DROP [ตารางถัดไป] ที่ด้านล่างของไฟล์
นาธาน

20
สำหรับการไม่เพิ่ม / ลบตาราง DROP จะมีประโยชน์มากกว่าในการจับคู่ตามTable structure for tableความคิดเห็นแทนที่จะจับคู่โดย CREATE TABLE สิ่งนี้จะช่วยให้มั่นใจได้ว่าตารางถัดไปจะไม่ถูกลบหากมีคนลืมลบคำสั่ง DROP TABLE และอนุญาตให้มีการไพพ์สำหรับการกู้คืนตารางคำสั่งเดียว (gzip | sed | mysql) อย่างไรก็ตามวิธีนี้ขึ้นอยู่กับไวยากรณ์ความคิดเห็น mysqldump (ฉันไม่ทราบว่ามันเป็นมาตรฐาน)
Olexa

12
ด้วยการดัดแปลงของ Olexa มันสมบูรณ์แบบ: sed -n -e '/ โครงสร้างตารางสำหรับ * `mytable /, / โครงสร้างตารางสำหรับ / p' whole.sql> mytable.sql
deeenes

120

ฉันใช้คำสั่ง sed ของ uloBasEI เวอร์ชันที่แก้ไขแล้ว มันมีคำสั่ง DROP ก่อนหน้าและอ่านจนกว่า mysql จะทำการถ่ายโอนข้อมูลไปยังตารางของคุณ (UNLOCK) ทำงานให้ฉัน (อีกครั้ง) นำเข้าwp_usersไปยังไซต์ Wordpress มากมาย

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' mydump.sql > tabledump.sql

3
นี่เป็นทางออกที่ดีกว่าคำตอบข้างต้น ไม่อยากเชื่อเลยว่าจะไม่ได้รับการโหวตเพิ่มขึ้นอีก
rICh

9
ฉันแนะนำให้เพิ่มอย่างน้อย backtick เครื่องหมายคำพูดในชื่อตาราง: `mytable`เพื่อหลีกเลี่ยงการจับคู่ตารางmytable2และอื่น ๆ เช่นเดียวกับในกรณีของฉัน
bartekbrak

3
คุณเพิ่งช่วยตูดฉัน
Gabriel Alack

1
@ user706420 อืมคุณแน่ใจหรือว่าเทอร์มินัลของคุณไม่ได้รับการตำหนิ? sedไม่ควรยุ่งเกี่ยวกับการเข้ารหัส ...
bryn

6
สำหรับผู้ที่มีไฟล์ SQL ที่ไม่ได้มีDROP TABLE(การถ่ายโอนข้อมูล MySQL ของฉันไม่มีสิ่งนี้) อาจต้องการใช้: sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql นี่เป็นการใช้ประโยชน์จากความคิดเห็นของตารางที่มีให้ก่อนแต่ละตารางในการถ่ายโอนข้อมูล MySQl และทำให้มั่นใจ/*!40101 SET @saved_cs_client = @@character_set_client */;ได้ว่า
hamx0r

50

สิ่งนี้สามารถทำได้ง่ายขึ้น? นี่คือวิธีที่ฉันทำ:

สร้างฐานข้อมูลชั่วคราว (เช่นกู้คืน):

mysqladmin -u root -p สร้างการคืนค่า

กู้คืนดัมพ์แบบเต็มในฐานข้อมูล temp:

mysql -u root -p restore <fulldump.sql

ดัมพ์ตารางที่คุณต้องการกู้คืน:

mysqldump กู้คืน mytable> mytable.sql

นำเข้าตารางในฐานข้อมูลอื่น:

ฐานข้อมูล mysql -u root -p <mytable.sql


2
นี่คือสิ่งที่คนส่วนใหญ่ต้องการ
sjas

2
ตามข้อเสนอแนะการแก้ไขนี้คุณควรเพิ่ม "--one ฐานข้อมูลพารามิเตอร์" เพื่อให้แน่ใจว่าคุณเรียกคืนเพียงหนึ่งในฐานข้อมูลและไม่ทำลายทุกสิ่งทุกอย่าง
SL Barth - Reinstate Monica

7
สำหรับฐานข้อมูลขนาดใหญ่จริงๆมันแปลกมาก - กู้คืนข้อมูล 150 GB สำหรับหนึ่งตาราง 100 MB
Enyby

ฉันเพิ่งรันสิ่งนี้โดยไม่มี "--one-database" และมันยังคงผสานตารางได้ดี มันไม่ได้ลบตารางที่มีอยู่ของฉัน
Qasim

1
การปฏิบัติที่เลวร้ายมาก! ฉันมีฐานข้อมูลไม่กี่ตัวในการถ่ายโอนข้อมูลและพยายามกู้คืนเพียงรายการเดียวลบข้อมูลทั้งหมด
AndreyP

11

ทางออกที่ง่ายคือการสร้างดัมพ์ของตารางที่คุณต้องการกู้คืนแยกจากกัน คุณสามารถใช้คำสั่ง mysqldump โดยใช้ไวยากรณ์ต่อไปนี้:

mysqldump -u [user] -p[password] [database] [table] > [output_file_name].sql

จากนั้นนำเข้าตามปกติและจะนำเข้าเฉพาะตารางที่ถูกทิ้ง


9

ไม่ทางใดก็ทางหนึ่งกระบวนการที่จะต้องดำเนินการผ่านข้อความทั้งหมดของการถ่ายโอนข้อมูลและแยกวิเคราะห์ในบางวิธี ฉันแค่ grep สำหรับ

INSERT INTO `the_table_i_want`

และท่อส่งออกเป็น mysql ดูที่ตารางแรกในการถ่ายโอนข้อมูลก่อนเพื่อให้แน่ใจว่าคุณได้รับ INSERT เป็นวิธีที่ถูกต้อง

แก้ไข: ตกลงจัดรูปแบบได้ในเวลานี้


ฉันเป็นคนโง่ที่ไม่ได้คิดที่จะโลภมันทันที Grep ช่วยเบคอนฉันทุกวันดูเหมือนว่า ข้อเสนอแนะอีกสองข้อนั้นเป็นคำตอบที่ไม่ดีและสิ่งที่ฉันจะทำโดยไม่ต้องใช้ grep ขอบคุณทุกคน!
Mobius

6
หากคุณคิดว่าคุณรัก grep เมื่อคุณเรียนรู้ awk คุณจะกลายเป็นทาสทางเพศที่มีความสุข: en.wikipedia.org/wiki/Awk
JCCyC

7

คุณควรลอง @bryn คำสั่ง แต่ด้วย `ตัวคั่น 'มิฉะนั้นคุณจะแยกตารางที่มีคำนำหน้าหรือคำต่อท้ายนี่คือสิ่งที่ฉันมักจะทำ:

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' dump.sql > mytable.sql

นอกจากนี้เพื่อวัตถุประสงค์ในการทดสอบคุณอาจต้องการเปลี่ยนชื่อตารางก่อนนำเข้า:

sed -n -e 's/`mytable`/`mytable_restored`/g' mytable.sql > mytable_restored.sql

ในการนำเข้าคุณสามารถใช้คำสั่ง mysql:

mysql -u root -p'password' mydatabase < mytable_restore.sql

6
  1. การสำรองข้อมูล

    $ mysqldump -A | gzip > mysqldump-A.gz
  2. คืนค่าตารางเดียว

    $ mysql -e "truncate TABLE_NAME" DB_NAME
    $ zgrep ^"INSERT INTO \`TABLE_NAME" mysqldump-A.gz | mysql DB_NAME

4

วิธีหนึ่งที่เป็นไปได้ในการจัดการกับสิ่งนี้คือการกู้คืนไปยังฐานข้อมูลชั่วคราวและดัมพ์เพียงตารางนั้นจากฐานข้อมูลชั่วคราว จากนั้นใช้สคริปต์ใหม่



3
sed -n -e '/-- Table structure for table `my_table_name`/,/UNLOCK TABLES/p' database_file.sql > table_file.sql

นี่เป็นทางออกที่ดีกว่าบางรายการข้างต้นเนื่องจากการทิ้ง SQL ไม่ได้มีDROP TABLEคำสั่ง หนึ่งนี้จะทำงานได้ทุกชนิดทิ้ง


2

สิ่งนี้อาจช่วยได้เช่นกัน

# mysqldump -u root -p database0 > /tmp/database0.sql
# mysql -u root -p -e 'create database database0_bkp'
# mysql -u root -p database0_bkp < /tmp/database0.sql
# mysql -u root -p database0 -e 'insert into database0.table_you_want select * from database0_bkp.table_you_want'

2

ตารางควรมีโครงสร้างเดียวกันทั้งในดัมพ์และฐานข้อมูล

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql.tar.gz | mysql -u<user> -p<password> database_name`

หรือ

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql | mysql -u<user> -p<password> database_name`

1

โปรแกรมแก้ไขข้อความที่ทันสมัยส่วนใหญ่ควรสามารถจัดการไฟล์ข้อความขนาดนั้นได้หากระบบของคุณเป็นไปตามที่กำหนด

อย่างไรก็ตามฉันต้องทำอย่างนั้นครั้งเดียวอย่างรวดเร็วและฉันไม่มีเวลาที่จะค้นหาเครื่องมือใด ๆ ฉันตั้งค่าอินสแตนซ์ MySQL ใหม่นำเข้าการสำรองข้อมูลทั้งหมดแล้วคายเพียงตารางที่ฉันต้องการ

จากนั้นฉันก็นำเข้าตารางนั้นไปยังฐานข้อมูลหลัก

มันน่าเบื่อ แต่ค่อนข้างง่าย โชคดี.


1

คุณสามารถใช้โปรแกรมแก้ไข vi ประเภท:

vi -o mysql.dump mytable.dump

ที่จะเปิดทั้งการถ่ายโอนข้อมูลทั้งหมดและไฟล์ใหม่mysql.dump mytable.dumpค้นหาแทรกที่เหมาะสมลงในบรรทัดโดยการกด/แล้วพิมพ์วลีตัวอย่างเช่น: "แทรก` mytable`" yyจากนั้นคัดลอกบรรทัดว่าการใช้ สลับไปยังไฟล์ต่อไปโดยctrl+wจากนั้นวางสายคัดลอกด้วยdown arrow key ppสุดท้ายบันทึกไฟล์ใหม่โดยการพิมพ์:wqและค่อนข้าง vi :qแก้ไขโดย

โปรดทราบว่าหากคุณทิ้งข้อมูลโดยใช้เม็ดมีดหลายอันคุณสามารถคัดลอก (งัด) ทั้งหมดในครั้งเดียวโดยใช้Nyyซึ่งNเป็นจำนวนบรรทัดที่จะคัดลอก

ฉันทำมันด้วยไฟล์ขนาด 920 MB


0

รับโปรแกรมแก้ไขข้อความที่ดีเช่น Notepad ++ หรือ Vim (หากคุณเชี่ยวชาญ) ค้นหาชื่อตารางและคุณควรจะสามารถเน้นเฉพาะคำสั่ง CREATE, ALTER และ INSERT สำหรับตารางนั้น การนำทางด้วยแป้นพิมพ์อาจง่ายกว่าใช้เมาส์ และฉันจะตรวจสอบให้แน่ใจว่าคุณอยู่ในเครื่องที่มีมากมายหรือ RAM เพื่อไม่ให้มีปัญหาในการโหลดไฟล์ทั้งหมดในครั้งเดียว เมื่อคุณเน้นและคัดลอกแถวที่คุณต้องการคุณควรสำรองข้อมูลส่วนที่คัดลอกไว้ในไฟล์สำรองของตัวเองแล้วนำเข้าลงใน MySQL


1
อันที่จริงแล้วมันเป็นเรื่องง่ายที่จะทำและเข้าใจได้แม้กระทั่งกับผู้เริ่มต้น ฉันไม่รู้ว่าทำไมสิ่งนี้จึงถูกลดระดับลง
Karl Johan Vallner

0

ชิ้นส่วนของ SQL จะถูกปิดกั้นด้วย "โครงสร้างตารางสำหรับตารางmy_table" และ "ข้อมูลการทุ่มตลาดสำหรับตารางmy_table"

คุณสามารถใช้บรรทัดคำสั่ง Windows ดังต่อไปนี้เพื่อรับหมายเลขบรรทัดสำหรับส่วนต่างๆ ปรับสตริงการค้นหาตามต้องการ

หา / n "สำหรับตาราง` "sql.txt

จะถูกส่งคืนดังต่อไปนี้:

---------- SQL.TXT

[4384] - โครงสร้างตารางสำหรับตาราง my_table

[4500] - การดัมพ์ข้อมูลสำหรับตาราง my_table

[4514] - โครงสร้างตารางสำหรับตาราง some_other_table

... ฯลฯ

นั่นทำให้คุณได้รับหมายเลขบรรทัดที่คุณต้องการ ... ตอนนี้ถ้าฉันรู้วิธีใช้มันเท่านั้น ...


0

ย้อนกลับไปในปี 08 ฉันก็ต้องทำเช่นนี้ด้วย ฉันเขียนสคริปต์ Perl ที่จะทำและตอนนี้มันเป็นวิธีการที่ฉันเลือก สรุปด้วยว่าจะทำอย่างไรใน awk หรือคืนค่าที่อื่นและแตกไฟล์ เมื่อเร็ว ๆ นี้ฉันได้เพิ่มวิธีการ sed นี้ในรายการเช่นกัน คุณสามารถค้นหาสคริปต์และวิธีอื่น ๆ ได้ที่นี่: http://blog.tsheets.com/2008/tips-tricks/extract-a-single-table-from-a-mysqldump-file.html



0

โซลูชัน 'sed' ที่กล่าวถึงข้างต้นนั้นดี แต่ดังที่กล่าวไว้ไม่ปลอดภัย 100%

  • คุณอาจมีคำสั่ง INSERT ที่มีข้อมูลประกอบด้วย: ... สร้างตาราง ... (อะไรก็ตาม) ... mytable ...

  • หรือแม้แต่สตริงที่แน่นอน "CREATE TABLE` mytable`; " หากคุณกำลังจัดเก็บคำสั่ง DML เช่น!

(และถ้าตารางมีขนาดใหญ่คุณไม่ต้องการตรวจสอบด้วยตนเอง)

ฉันจะตรวจสอบไวยากรณ์ที่แน่นอนของเวอร์ชันดัมพ์ที่ใช้และมีการค้นหารูปแบบที่ จำกัด ยิ่งขึ้น:

หลีกเลี่ยง ". *" และใช้ "^" เพื่อให้แน่ใจว่าเราเริ่มต้นจากจุดเริ่มต้น และฉันต้องการคว้า 'DROP' เริ่มต้น

ทั้งหมดนี้ใช้ได้ดีกับฉัน:

sed -n -e '/^DROP TABLE IF EXISTS \`mytable\`;/,/^UNLOCK TABLES;/p' mysql.dump > mytable.dump
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.