ลบ DEFINER clause จาก MySQL Dumps


114

ฉันมี MySQL ดัมพ์ของหนึ่งในฐานข้อมูลของฉัน ในนั้นมีประโยค DEFINER ซึ่งมีลักษณะดังนี้

"DEFINER=`root`@`localhost`" 

กล่าวคือคำสั่ง DEFINER เหล่านี้อยู่ในคำสั่ง CREATE VIEW และ CREATE PROCEDURE มีวิธีลบคำสั่ง DEFINER เหล่านี้ออกจากไฟล์ดัมพ์ของฉันหรือไม่


มีรายงานข้อผิดพลาดเมื่อหลายปีก่อน แต่ดูเหมือนจะถูกทิ้ง: bugs.mysql.com/bug.php?id=24680
1234ru

คำตอบ:


109

ฉันไม่คิดว่าจะมีวิธีละเว้นการเพิ่มDEFINERs ลงในดัมพ์ แต่มีวิธีลบออกหลังจากสร้างไฟล์ดัมพ์แล้ว

  1. เปิดไฟล์ดัมพ์ในโปรแกรมแก้ไขข้อความและแทนที่เหตุการณ์ทั้งหมดDEFINER=root@localhostด้วยสตริงว่าง ""

  2. แก้ไขดัมพ์ (หรือไพพ์เอาต์พุต) โดยใช้perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. บีบเอาต์พุตผ่านsed:

    mysqldump ... | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > triggers_backup.sql

1
@FastTrack โปรดลบสตริงทั้งหมด
Abhay

3
ฉันขอแนะนำให้พูดถึงว่าแทนที่จะลบ DEFINER สามารถตั้งค่าเป็น CURRENT_USER ได้เช่นนั้น: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlมีข้อดีในการรักษาข้อ จำกัด / การควบคุมการเข้าถึง
4thfloorstudios

27
sedคำสั่งไม่เอาข้อ definer จากวิธีการและฟังก์ชั่น นี่คือเวอร์ชันขั้นสูงที่จัดการกับมุมมองทริกเกอร์ขั้นตอนและฟังก์ชัน: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
FYI --- แม้ว่าตอนนี้จะไม่ได้รับคำตอบ แต่ตอนนี้ MySQL> 5.6 มาพร้อมกับ mysqldump (1) ที่รองรับ "--skip-Definer" เป็นตัวเลือก: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey

4
ไม่มันไม่ใช่ mysqldump แต่เป็น mysql p ump ที่มี --skip-Definer
Xdg

70

คุณสามารถลบโดยใช้ SED

sed -i 's/DEFINER=[^*]*\*/\*/g' mydump.sql

ใน MacOS:

sed -i '' 's/DEFINER=[^*]*\*/\*/g' mydump.sql

สิ่งที่เกิดขึ้นใน MacOS จะแตกต่างกันอย่างไร?
Alex

1
manpage สำหรับ sed บน mac ระบุว่า: -i extension"แก้ไขไฟล์ในสถานที่บันทึกการสำรองข้อมูลด้วยนามสกุลที่ระบุหากกำหนดส่วนขยายที่มีความยาวเป็นศูนย์จะไม่มีการบันทึกข้อมูลสำรองไม่แนะนำให้ใส่นามสกุลที่มีความยาวเป็นศูนย์เมื่อ ไฟล์แก้ไขในสถานที่เนื่องจากคุณเสี่ยงต่อความเสียหายหรือเนื้อหาบางส่วนในสถานการณ์ที่เนื้อที่ดิสก์หมดเป็นต้น "
ชาด

ยินดีที่ได้รู้จัก @Chad. ฉันใช้ sed แบบนี้ใน mac มา 5 ปีแล้ว ฉันไม่เคยมีปัญหาเกี่ยวกับพื้นที่ว่างหรือไฟล์ที่เสียหาย แต่แน่นอนเป็นสิ่งที่ต้องพิจารณา ขอบคุณสำหรับความกระจ่าง
Ricardo Martins

ฉันไม่เคยพบปัญหาเหล่านั้นบน Mac เช่นกัน แค่คิดว่าฉันจะชี้แจงตั้งแต่ @Alex ถาม :)
ชาด

57

เนื่องจาก mysql เวอร์ชัน 5.7.8 คุณสามารถใช้--skip-definerตัวเลือกนี้กับ mysqlpump เช่น:

mysqlpump --skip-definer -h localhost -u user -p yourdatabase

ดูคู่มือ mysql ฉบับปรับปรุงได้ที่http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer


8
สำหรับใครที่สงสัยว่าความแตกต่างระหว่างmysqldumpและmysqlpump- นี่คือคำถามที่เกี่ยวข้อง: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

ฉันติดตั้ง phpMyAdmin และ MySQL Workbench แล้ว ฉันจะรันคำสั่งนี้บน Windows ได้อย่างไร?
posfan12

(หลังจากการทดสอบบางครั้ง: -1) ใช้information_schema.userและสิ่งนี้ไม่สามารถอ่านได้สำหรับผู้ใช้ทุกคน
bato3

17

ฉันใช้แนวคิดเหล่านี้เพื่อตัดส่วนคำสั่ง DEFINER จากเอาต์พุต mysqldump ของฉันเอง แต่ฉันใช้วิธีที่ง่ายกว่า:

เพียงแค่ลบ!ก่อนรหัสและ DEFINER ความคิดเห็นที่เหลือจะกลายเป็นความคิดเห็นปกติ

ตัวอย่าง:

/*!50017 DEFINER=`user`@`111.22.33.44`*/

ทำอะไรไม่ถูกเลยแม้แต่น้อยที่ทำแบบนี้ ..

/* 50017 DEFINER=`user`@`111.22.33.44`*/

regexp ที่ง่ายที่สุดคือการลบ! และตัวเลข

mysqldump | /usr/bin/perl -pe 's/\!\d+ DEFINER/DEFINER/' > dumpfile.sql

ซึ่งจะลบ!#### DEFINERและแทนที่ด้วย DEFINER ... คุณสามารถลบ DEFINER ได้เช่นกันมันไม่สำคัญเลย - เมื่อ "!" หายไป


16

ตามคำแนะนำของผู้อื่นต่อไปนี้เป็นตัวอย่างวิธีการลบ DEFINER ออกจากดัมพ์หลังจากการถ่ายโอนข้อมูลเสร็จสิ้น:

mysqldump -u user --password='password' -h localhost database | grep -v "50013 DEFINER" > dump.sql

4
สำหรับทริกเกอร์เส้นจะมีลักษณะดังนี้ / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 ทริกเกอร์ my_triggername ก่อนใส่ my_table สำหรับแต่ละแถว .... * / ;; และgrep -vจะทิ้งบรรทัดเหล่านั้นทั้งหมด (แม้ว่า 50017! = 50013)
Kenney

13

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

นี่คือนิพจน์ทั่วไปที่ใช้ได้ผลสำหรับฉัน:

sed -e 's/DEFINER=[^ ]* / /'

และเร็วขึ้น ^^ ขอบคุณ
Kevin Labécot

1
ใช้ไม่ได้กับทริกเกอร์ - ลบไฟล์*/. MySQL 5.6.31
Franc Drobnič

10

mysqlmigrateสำหรับวิธีการแบบอัตโนมัติคุณสามารถดู มันเป็น Bash wrapper mysqldumpที่ให้คุณย้ายฐานข้อมูลและละเว้นคำสั่ง DEFINER ตัวอย่าง:

$ mysqlmigrate -u root -p pass --ignore-definer from_db to_db

http://thesimplesynthesis.com/post/mysqlmigrate (หรือGitHub )

มิฉะนั้นใช่คำสั่งเช่น Abhay ชี้ให้เห็นเป็นสิ่งจำเป็น:

$ mysqldump -u root -ppass the_db | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > the_db.sql

6

อีกทางเลือกหนึ่งบน OSX เพื่อลบตัวกำหนดในไฟล์:

sed -i '' 's/DEFINER=`[^`][^`]*`@`[^`][^`]*`//g' file.sql

5

คุณควรดูคำตอบที่นี่: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

วิธีที่ดีที่สุดในความคิดของฉันในการแก้ไขปัญหานี้ไม่ใช่การเพิ่มการแยกวิเคราะห์สตริงพิเศษด้วย sed หรือ grep หรืออื่น ๆ แทน mysqldump สามารถสร้างการถ่ายโอนข้อมูลที่ดีโดยการเพิ่ม - single-transaction


ทำไมโหวตลง? ทำไมคำตอบนี้จึงไม่ถือว่าเป็นประโยชน์?
Jose Nobile

1
คำตอบของคุณยังต้องการการโหวตมากกว่า 90 คะแนนเพื่อให้ได้ตำแหน่งที่สมควรได้รับ คุณมีของฉัน :)
Patrick van Bergen

4

วิธีที่รวดเร็วในการทำเช่นนี้คือการไพพ์เอาต์พุตของmysqldumpผ่านsedเพื่อลบDEFINERข้อความที่อยู่ในความคิดเห็นที่มีเงื่อนไข ฉันใช้สิ่งนี้เพื่อลบออกDEFINERจากCREATE TRIGGERคำสั่ง แต่คุณสามารถปรับแต่งหมายเลขเวอร์ชันความคิดเห็นเงื่อนไขใน regex เพื่อให้เหมาะกับวัตถุประสงค์ของคุณ

mysqldump -u user --password='password' -h localhost database | \
  sed 's/\/\*!50017 DEFINER=`.*`@`.*`\*\///' 

1
คำสั่ง sed ที่อ่านง่ายกว่าเล็กน้อย: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

ไม่แน่ใจว่าจะช่วยได้หรือไม่ แต่ฉันใช้ SQLyog Community Edition ที่: -

https://code.google.com/p/sqlyog/wiki/Downloads

เมื่อทำการถ่ายโอนข้อมูล sql หรือคัดลอกไปยังฐานข้อมูลอื่นจะอนุญาตให้คุณ 'ละเว้น DEFINER'

ฟรีและมีฟังก์ชันพื้นฐานที่ผู้คนจำนวนมากต้องการ

นอกจากนี้ยังมีเวอร์ชันที่ต้องชำระเงินจาก: -

https://www.webyog.com/product/sqlyog

ไชโย


แทนที่จะตั้งค่าสถานะว่า 'ไม่มีประโยชน์' บางทีมันอาจจะมีประโยชน์มากกว่าถ้าคุณตอบกลับไปว่าทำไมคุณถึงรู้สึกว่ามันไม่มีประโยชน์?
itfidds

3

สำหรับฉันสิ่งนี้ได้ผล: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. สิ่งนี้ลบ DEFINER = root @ localhost ออกจากดัมพ์ของฉันในการสร้างโพรซีเดอร์แต่ละรายการ


2

นี่คือโซลูชันการทำงานที่สมบูรณ์เพื่อลบข้อมูล DEFINER สำหรับMySQL 5.6.xและ Linux (ทดสอบแล้วCentOS 6.5)

โดยปกติเราต้องแทนที่รายการต่อไปนี้จากการถ่ายโอนข้อมูล Mysql (หากนำมาพร้อมกับข้อมูลและทริกเกอร์ / กิจวัตร / ฟังก์ชัน)

/*!50013 DEFINER=`MYSQLUSER`@`localhost` SQL SECURITY DEFINER */
/*!50013 DEFINER=`MYSQLUSER`@`%` SQL SECURITY DEFINER */
CREATE DEFINER=`MYSQLUSER`@`%` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`%` FUNCTION `FUNCTIONNAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` FUNCTION `FUNCTIONNAME`(
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`%`*/ /*!50003 TRIGGER `TRIGGERNAME`
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`localhost`*/ /*!50003 TRIGGER `TRIGGERNAME`

ถ่ายโอนข้อมูลด้วยคำสั่ง mysqldump ด้านล่าง

mysqldump -uMYSQLUSER -pPASSWORD DATABASENAME -R > dbdump.sql

ไฟล์ดัมพ์ที่ต้องการโดยไม่มีข้อมูล DEFINER สามารถรับได้ด้วยคำสั่งด้านล่างสามคำสั่ง

Command-1    
sed -i 's|DEFINER=[^*]*\*|\*|g' [PATH/]dbdump.sql

Command-2
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`localhost\`//"

Command-3
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`%\`//"

หากไฟล์ดัมพ์อยู่ในโฟลเดอร์ปัจจุบันของคุณให้ละเว้น [PATH /]

หากข้อมูลในตารางมีขนาดใหญ่มากให้ใช้การถ่ายโอนข้อมูลในสองไฟล์ในไฟล์ดัมพ์หนึ่งไฟล์จะทำการดัมพ์พร้อมกับข้อมูลและในไฟล์ดัมพ์อื่น ๆ ที่ใช้ดัมพ์ของสคริปต์เท่านั้น (ทริกเกอร์ / ฟังก์ชัน / โพรซีเดอร์) และรันสามไฟล์ข้างต้น คำสั่งบนไฟล์ดัมพ์ (สคริปต์) ที่ 2


1

แทนที่ผู้ใช้ที่แน่นอนทั้งหมดของคุณด้วย CURRENT_USER ในสคริปต์ gradle ของฉันที่สร้างการสำรองข้อมูลสคริปต์การแทนที่ของฉันดูเหมือน:

ant.replaceregexp(file: "$buildDir/sql/setupDB.sql", match: "`${project.ext.prod_db_username}`@`%`", replace: "CURRENT_USER", byline: true);

ซึ่งจริงๆแล้วเรียกว่า ANT แล้วคุณจะไม่ต้องกังวลเกี่ยวกับมัน


1

บนเครื่อง Linux คุณสามารถใช้ซับเดียวนี้:

mysql -uuser -ppwd -A --skip-column-names -e"SELECT CONCAT('SHOW CREATE VIEW ',table_schema,'.',table_name,';') FROM information_schema.tables WHERE engine IS NULL and table_schema like 'mydb%'" | mysql -uuser -ppwd -A --skip-column-names | sed -rn 's/.*?VIEW ([^\s]+?) (AS .*?)\s([^\s]+?)\s([^\s]+?)/DROP VIEW \1;\nCREATE VIEW \1 \2;/p' | mysql -uuser -ppwd -A --skip-column-names

คุณต้องแทนที่สตริงเป็นตัวหนาด้วยข้อมูลรับรองผู้ใช้ DB และชื่อฐานข้อมูล / รูปแบบเหมือนเท่านั้น

ข้อมูลเพิ่มเติมที่นี่: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

วิธีเดียวที่ฉันจะทำให้มันทำงานภายใต้ Windows:

ติดตั้งhttp://gnuwin32.sourceforge.net/เพื่อให้sedในบรรทัดคำสั่งและเพิ่มลงใน Windows PATH: D: \ programs \ GetGnuWin32 \ bin;

sed -i "s|DEFINER=`mydbuser`@`%%` SQL SECURITY DEFINER||g" "D:/prod_structure.sql"

sed -i "s|DEFINER=`mydbuser`@`%%`||g" "D:/prod_structure.sql"

mysqldump -P{port} -h{host} -u{user} -p{password} --routines --no-data --lock-tables=false database_prod > D:\prod_structure.sql

1

ขอบคุณทุกคำชี้แนะ ด้วยความขี้เกียจฉันเขียนสคริปต์ชื่อ: "MYsqldump":

DB=$1
HOST=$2
USER=$3
MYSQLDUMP='/usr/bin/mysqldump'
PARAMS="--complete-insert --disable-keys=0 --extended-insert=0 --routines=0 --skip-comments"
DAY=`date +%d`
MONTH=`date +%m`
YEAR=`date +%Y`
FILE=$DB.$DAY-$MONTH-$YEAR.sql

    if (( $# < 3 )) ; then
        echo ""
        echo "usage: MYsqldump <db> <host> <user>"
        echo ""
        exit 1
    fi

    $MYSQLDUMP -h $HOST -u $USER -p  $PARAMS $DB | grep -v '/*!50013 DEFINER' > $FILE

1

สำหรับสิ่งที่ชอบ:

DELIMITER ;;
สร้าง DEFINER = `mydb` @` localhost` FUNCTION `myfunction` () RETURNS int (11)
เริ่ม
( ... )
จบ ;;

ลองสิ่งนี้:

mysqldump --force --routines --opt --user = myuser - ฐานข้อมูล mydb | sed -e 's / DEFINER =“. * `@“. *` \ // g'

1
  1. เปิดฐานข้อมูลของคุณด้วยโปรแกรมแก้ไขใด ๆ ที่ฉันใช้กับ notepad ++

  2. ค้นหาการทดสอบทั้งหมดDEFINER=root@localhost และแทนที่ด้วยอะไร ( "") IE ลบมัน.

จากนั้นคุณสามารถนำเข้าโฮสต์ใดก็ได้ที่คุณต้องการ


0

regex ที่ง่ายที่สุดที่เหมาะกับฉันกับวัตถุทั้งหมดคือ:

sed 's/DEFINER=[^ ]*`//' ...

โปรดทราบว่าquote-namesต้องเป็นTRUE(ซึ่งโดยค่าเริ่มต้น)

หวังว่าในเวอร์ชันที่ใหม่กว่าสวิตช์ที่--skip-definerเปิดตัวใน mysqlpump ในเวอร์ชัน 5.7 จะมาถึง mysqldump ด้วย


0

ฉันใช้สคริปต์ PowerShell เพื่อลบบรรทัดทั้งหมดด้วยDEFINER:

รับเนื้อหา $ file_in_full_path | เลือกสตริง - รูปแบบ $ line_string_delete -notmatch | ไฟล์ออก - ความกว้าง 1000000000 - เข้ารหัสเริ่มต้น $ file_out_full_path


0

ไม่มีอะไรได้ผลสำหรับฉันดังนั้นฉันจึงต้องเขียนนิพจน์ทั่วไปของตัวเอง

  1. พยายามทิ้งฐานข้อมูลของคุณลงในไฟล์catทั้งไฟล์และgrepเฉพาะคำสั่งที่ชัดเจนของคุณเพื่อดู

    cat file.sql | grep -o -E ". {, 60} DEFINER. {, 60} '

  2. เขียน regex ของคุณ

  3. บีบดัมพ์ของคุณให้เป็น sed ด้วยนิพจน์นี้ ตัวอย่างเช่นคำสั่งของฉันคือ:

    mysqldump | sed -E // *! 500 [0-9] [0-9] DEFINER =. +? * /// '| sed -E ของ / DEFINER = ?[^ ]+?? @ ?[^ ]+?? // '

  4. กำไร!


0

remove_definers.bat:

@echo off
(for /f "tokens=1,2*" %%a in (dumpfile.sql) do (
 if "%%b"=="" (echo %%a) else (
  echo %%b | find "DEFINER" > null && echo %%a %%c || echo %%a %%b %%c
 )
)) > dumpfile_nodefiners.sql
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.