Xóa mệnh đề DEFINER khỏi MySQL Dumps


114

Tôi có một kết xuất MySQL của một trong các cơ sở dữ liệu của tôi. Trong đó, có các mệnh đề DEFINER trông giống như,

"DEFINER=`root`@`localhost`" 

Cụ thể, các mệnh đề DEFINER này nằm trong câu lệnh CREATE VIEW và CREATE PROCEDURE của tôi. Có cách nào để xóa các mệnh đề DEFINER này khỏi tệp kết xuất của tôi không?


Một lỗi đã được báo cáo năm trước đây, nhưng có vẻ bị bỏ rơi: bugs.mysql.com/bug.php?id=24680
1234ru

Câu trả lời:


109

Tôi không nghĩ có cách nào để bỏ qua việc thêm DEFINERs vào bãi chứa. Nhưng có nhiều cách để xóa chúng sau khi tệp kết xuất được tạo.

  1. Mở tệp kết xuất trong trình soạn thảo văn bản và thay thế tất cả các lần xuất hiện của DEFINER=root@localhostbằng một chuỗi trống ""

  2. Chỉnh sửa kết xuất (hoặc chuyển đầu ra) bằng cách sử dụng perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Đưa đầu ra thông qua sed:

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

1
@FastTrack, vui lòng xóa toàn bộ chuỗi.
Abhay

3
Tôi đề nghị đề cập rằng thay vì xóa DEFINER, nó có thể được đặt thành CURRENT_USER như vậy: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlNó có lợi thế là giữ các hạn chế / kiểm soát truy cập.
4thfloorstudios

27
Các sedlệnh không loại bỏ khoản DEFINER từ thủ tục và hàm. Dưới đây là phiên bản cải tiến cho phép xử lý các quan điểm, gây nên, thủ tục và chức năng: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
FYI --- mặc dù nó không phải là trường hợp tại thời điểm câu trả lời này, MySQL> 5.6 hiện đi kèm với mysqldump (1) hỗ trợ "--skip-definer" như một tùy chọn: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey

4
Không, không phải mysqldump mà là mysql p ump có --skip-definer.
Xdg

70

Bạn có thể xóa bằng SED

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

Trong MacOS:

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

Điều gì đang xảy ra ở đây trong MacOS để trở nên khác biệt?
Alex

1
Trang chủ dành cho sed trên mac cho biết điều này: -i extension"Chỉnh sửa tệp tại chỗ, lưu bản sao lưu với phần mở rộng được chỉ định. Nếu phần mở rộng có độ dài bằng 0 được cung cấp, sẽ không có bản sao lưu nào. Bạn không nên cung cấp phần mở rộng có độ dài bằng 0 khi các tệp chỉnh sửa tại chỗ, vì bạn có nguy cơ bị hỏng hoặc một phần nội dung trong tình huống hết dung lượng đĩa, v.v. "
Chad

Rất vui được biết điều đó, @Chad. Tôi đang sử dụng sed như thế này trong mac hơn 5 năm nay. Tôi chưa bao giờ gặp vấn đề với dung lượng hoặc tệp bị hỏng. Nhưng tất nhiên, là một cái gì đó để xem xét. Cảm ơn đã làm rõ.
Ricardo Martins

Tôi cũng chưa bao giờ gặp phải những vấn đề đó trên Mac. Chỉ nghĩ rằng tôi sẽ làm rõ vì @Alex hỏi :)
Chad

57

Kể từ phiên bản mysql 5.7.8, bạn có thể sử dụng --skip-definertùy chọn với mysqlpump, ví dụ:

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

Xem hướng dẫn sử dụng mysql cập nhật tại http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer


8
Đối với bất kỳ ai tự hỏi sự khác biệt giữa mysqldumpmysqlpump- đây là câu hỏi liên quan: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge,

Tôi đã cài đặt phpMyAdmin và MySQL Workbench. Làm cách nào để thực hiện lệnh này trên Windows?
posfan 12

(sau khi một số xét nghiệm: -1) Nó sử dụng information_schema.user, và điều này không phải lúc nào cũng có thể đọc được cho tất cả người dùng
bato3

17

Tôi đã sử dụng những ý tưởng này để loại bỏ mệnh đề DEFINER khỏi đầu ra mysqldump của riêng tôi, nhưng tôi đã thực hiện một cách tiếp cận đơn giản hơn:

Chỉ cần xóa phần !trước mã và DEFINER, phần còn lại của nhận xét sẽ trở thành nhận xét bình thường.

Thí dụ:

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

được đưa ra bất lực, ít khi làm điều này ..

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

Tuy nhiên, regexp dễ dàng nhất là loại bỏ! và những con số

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

Điều đó sẽ xóa !#### DEFINERvà thay thế bằng DEFINER ... bạn cũng có thể xóa DEFINER, điều đó không thực sự quan trọng - một khi dấu "!" đã biến mất


16

Theo khuyến nghị của những người khác, đây là một ví dụ về cách xóa DEFINER khỏi kết xuất, sau khi kết thúc kết thúc:

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

4
Đối với trình kích hoạt, các dòng trông giống như / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 kích hoạt my_triggername TRƯỚC KHI CHÈN TRÊN my_table CHO TỪNG ROW .... * / ;; và grep -vsẽ bỏ những dòng đó hoàn toàn. (mặc dù 50017! = 50013)
Kenney

13

Như những người khác đã đề cập, việc loại bỏ trình xác định với bất kỳ loại biểu thức chính quy nào không quá phức tạp. Nhưng các ví dụ khác đã tước bỏ các định nghĩa về khung nhìn đối với tôi.

Đây là biểu thức chính quy phù hợp với tôi:

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

Và nhanh hơn ^^ Cảm ơn
Kevin Labécot

1
Không hoạt động với trình kích hoạt - cũng loại bỏ */. MySQL 5.6.31.
Franc Drobnič

10

Đối với một giải pháp tự động, bạn có thể xem mysqlmigrate. Đó là một trình bao bọc Bash mysqldumpcho phép bạn di chuyển cơ sở dữ liệu và bỏ qua các câu lệnh DEFINER. Thí dụ:

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

http : //thesi samplesynthesis.com/post/mysqlmigrate (hoặc GitHub )

Nếu không, có, một lệnh như Abhay chỉ ra là cần thiết:

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

6

Một tùy chọn khác trên OSX để xóa bộ định nghĩa trong tệp:

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

5

Bạn nên xem câu trả lời ở đây: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

Theo ý kiến ​​của tôi, cách tốt nhất để giải quyết vấn đề này là không thêm một chuỗi phân tích cú pháp bổ sung với sed hoặc grep hoặc bất kỳ cách nào khác, thay vào đó mysqldump có thể tạo một kết xuất tốt bằng cách thêm --single-transaction


Tại sao phản đối? Tại sao câu trả lời này không được coi là hữu ích?
Jose Nobile

1
Phản hồi của bạn vẫn cần khoảng 90 lượt ủng hộ để có được vị trí xứng đáng. Bạn có của tôi :)
Patrick van Bergen

4

Một cách nhanh chóng để làm điều này là chuyển đầu ra của mysqldump thông qua sed để loại bỏ các DEFINERcâu lệnh được bao bọc trong các nhận xét có điều kiện. Tôi sử dụng điều này để xóa DEFINERkhỏi các CREATE TRIGGERcâu lệnh, nhưng bạn có thể điều chỉnh số phiên bản nhận xét điều kiện trong regex cho phù hợp với mục đích của mình.

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

1
Câu lệnh sed dễ đọc hơn một chút: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

Không chắc liệu nó có hữu ích không nhưng tôi sử dụng SQLyog Community Edition, có sẵn tại: -

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

Khi kết xuất sql hoặc sao chép vào cơ sở dữ liệu khác, nó cho phép bạn 'Bỏ qua ĐỊNH NGHĨA'

Nó miễn phí và cung cấp các chức năng cơ bản mà nhiều người yêu cầu

Cũng có một phiên bản trả phí có sẵn từ: -

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

Chúc mừng


Thay vì chỉ gắn cờ là 'không hữu ích' có lẽ sẽ hữu ích hơn nếu bạn trả lời với lý do tại sao bạn cảm thấy nó không hữu ích?
itfidds

3

Đối với tôi, công trình này: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. Điều này đã loại bỏ DEFINER = root @ localhost khỏi kết xuất của tôi, trên mỗi trạng thái thủ tục tạo


2

Đây là một giải pháp hoạt động hoàn chỉnh để xóa thông tin DEFINER cho MySQL 5.6.xvà Linux. (Đã thử nghiệm trên CentOS 6.5).

Thông thường, chúng tôi phải thay thế các mục sau từ kết xuất Mysql (nếu được sử dụng cùng với dữ liệu và trình kích hoạt / thói quen / chức năng).

/*!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`

Kết xuất được thực hiện bằng lệnh mysqldump bên dưới.

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

Tệp kết xuất bắt buộc không có thông tin DEFINER có thể được lấy bằng ba lệnh dưới đây.

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\`@\`%\`//"

Nếu tệp kết xuất nằm trong thư mục hiện tại của bạn thì hãy bỏ qua [PATH /].

Nếu dữ liệu trong các bảng rất lớn thì lấy kết xuất trong hai tệp, trong một tệp kết xuất lấy dữ liệu và trong tệp kết xuất khác chỉ lấy kết xuất các tập lệnh (Trình kích hoạt / Hàm / Thủ tục.) Và chạy ba tệp trên lệnh trên tệp kết xuất (script) thứ 2.


1

Thay thế tất cả người dùng xác định của bạn bằng CURRENT_USER. Trong tập lệnh gradle tạo bản sao lưu của tôi, tập lệnh thay thế của tôi trông giống như:

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

mà thực sự chỉ là gọi ANT. Sau đó, bạn sẽ không phải lo lắng về nó.


1

Trên các máy Linux, bạn có thể sử dụng một lớp lót này:

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

Bạn chỉ phải thay thế các chuỗi in đậm bằng thông tin đăng nhập người dùng DB và tên cơ sở dữ liệu / mẫu giống như.

Thông tin thêm tại đây: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

Cách duy nhất tôi có thể làm cho nó hoạt động trong Windows:

Cài đặt http://gnuwin32.sourceforge.net/ để có sed trong dòng lệnh và thêm nó vào 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

Cảm ơn tất cả các bạn cho những gợi ý. Do lười biếng, tôi đã viết một kịch bản có tên: "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

Đối với một cái gì đó như:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNCTION `my functions` () RETURNS int (11)
bắt đầu
(...)
kết thúc ;;

Thử cái này:

mysqldump --force --routines --opt --user = myuser --databases mydb | sed -e 's / DEFINER = `. *` @ `. *` \ // g'

1
  1. mở cơ sở dữ liệu của bạn bằng bất kỳ trình soạn thảo nào, tôi đã sử dụng với notepad ++,

  2. tìm tất cả thử nghiệm đó DEFINER=root@localhost và thay thế nó bằng không ( "") IE. xóa đi.

Sau đó, bạn có thể nhập nó vào bất kỳ máy chủ nào mà bạn muốn.


0

Regex đơn giản nhất phù hợp với tôi với tất cả các đối tượng là:

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

Lưu ý rằng quote-namesphải được TRUE(theo mặc định).

Hy vọng rằng trong các phiên bản mới hơn, công tắc được --skip-definergiới thiệu trong mysqlpump trong phiên bản 5.7 cũng sẽ xuất hiện trên mysqldump.


0

Tôi đã sử dụng tập lệnh PowerShell để xóa tất cả các dòng có DEFINER:

get-content $ file_in_full_path | select-string -pattern $ line_string_delete -notmatch | Ngoài tệp-băng thông 1000000000-Mã hóa mặc định $ file_out_full_path


0

Không có gì hiệu quả với tôi, vì vậy tôi cần phải viết regex của riêng mình.

  1. Cố gắng kết xuất cơ sở dữ liệu của bạn vào tệp, cattoàn bộ tệp vàgrep chỉ các câu lệnh xác định của bạn để xem chúng.

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

  2. Viết regex của bạn

  3. Đưa bãi rác của bạn vào sed với regex này. Ví dụ câu lệnh của tôi là:

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

  4. Lợi nhuận!


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