Hapus klausa DEFINER dari MySQL Dumps


114

Saya memiliki dump MySQL dari salah satu database saya. Di dalamnya terdapat klausul DEFINER yang terlihat seperti,

"DEFINER=`root`@`localhost`" 

Yakni, klausul DEFINER ini ada di pernyataan CREATE VIEW dan CREATE PROCEDURE saya. Apakah ada cara untuk menghapus klausa DEFINER ini dari file dump saya?


Sebuah bug telah dilaporkan beberapa tahun yang lalu, tetapi tampaknya telah ditinggalkan: bugs.mysql.com/bug.php?id=24680
1234ru

Jawaban:


109

Saya rasa tidak ada cara untuk mengabaikan penambahan DEFINERs ke dump. Tetapi ada cara untuk menghapusnya setelah file dump dibuat.

  1. Buka file dump di editor teks dan ganti semua kemunculan DEFINER=root@localhostdengan string kosong ""

  2. Edit dump (atau pipa output) menggunakan perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Pipa keluaran melalui sed:

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

1
@FastTrack, hapus seluruh string.
Abhay

3
Saya menyarankan untuk menyebutkan bahwa alih-alih menghapus DEFINER itu dapat diatur ke CURRENT_USER seperti itu: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlIni memiliki keuntungan menjaga pembatasan / kontrol akses.
4thfloorstudios

27
The sedperintah tidak menghapus Definer klausul dari prosedur dan fungsi. Berikut adalah versi yang disempurnakan yang menangani tampilan, pemicu, prosedur, dan fungsi: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
FYI --- meskipun tidak terjadi pada saat jawaban ini, MySQL> 5.6 sekarang dikirimkan dengan mysqldump (1) yang mendukung "--skip-definer" sebagai opsi: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey

4
Tidak, ini bukan mysqldump, tapi mysql p ump yang memiliki --skip-definer.
Xdg

70

Anda dapat menghapus menggunakan SED

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

Di MacOS:

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

Apa yang terjadi di sini di MacOS agar berbeda?
Alex

1
Halaman manual untuk sed di mac mengatakan ini: -i extension"Edit file di tempat, simpan cadangan dengan ekstensi yang ditentukan. Jika ekstensi panjang-nol diberikan, tidak ada cadangan yang akan disimpan. Tidak disarankan untuk memberikan ekstensi panjang-nol ketika file pengeditan di tempat, karena Anda berisiko mengalami kerusakan atau sebagian konten dalam situasi di mana ruang disk habis, dll. "
Chad

Senang mengetahuinya, @Chad. Saya menggunakan sed seperti ini di mac selama 5+ tahun sekarang. Saya tidak pernah mengalami masalah dengan ruang atau file yang rusak. Tapi tentu saja, ini sesuatu yang perlu dipertimbangkan. Terima kasih telah menjelaskan.
Ricardo Martins

Saya juga tidak pernah mengalami masalah itu di Mac. Hanya berpikir saya akan mengklarifikasi sejak @Alex bertanya :)
Chad

57

Sejak mysql versi 5.7.8 Anda dapat menggunakan --skip-defineropsi dengan mysqlpump, misalnya:

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

Lihat manual mysql yang diperbarui di http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer


8
Bagi siapa pun yang bertanya-tanya apa perbedaan antara mysqldumpdan mysqlpump- ini pertanyaan terkait: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

Saya telah menginstal phpMyAdmin dan MySQL Workbench. Bagaimana cara menjalankan perintah ini di Windows?
posfan12

(setelah beberapa tes: -1) Ini digunakan information_schema.user, dan ini tidak selalu dapat dibaca untuk semua pengguna
bato3

17

Saya menggunakan ide-ide ini untuk menghapus klausa DEFINER dari keluaran mysqldump saya sendiri, tetapi saya mengambil pendekatan yang lebih sederhana:

Hapus saja !sebelum kode dan DEFINER, dan sisa komentar menjadi komentar biasa.

Contoh:

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

menjadi tidak berdaya, hanya dengan melakukan ini ..

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

Namun, regexp termudah adalah dengan menghapus! dan nomornya

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

Itu menghapus !#### DEFINERdan mengganti dengan DEFINER ... Anda juga dapat menghapus DEFINER, itu tidak terlalu penting - setelah "!" hilang


16

Sesuai rekomendasi pihak lain, berikut adalah contoh cara menghapus DEFINER dari dump, setelah dump selesai:

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

4
Untuk pemicu, garisnya terlihat seperti / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 trigger my_triggername SEBELUM MASUKKAN DI my_table UNTUK SETIAP BARIS .... * / ;; dan grep -vakan menghapus garis itu seluruhnya. (meskipun 50017! = 50013)
Kenney

13

Seperti yang disebutkan orang lain, menghapus definer dengan jenis ekspresi reguler apa pun tidaklah terlalu rumit. Tetapi contoh lain melucuti definisi tampilan bagi saya.

Ini adalah ekspresi reguler yang berhasil untuk saya:

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

Dan lebih cepat ^^ Terima kasih
Kevin Labécot

1
Tidak berfungsi dengan pemicu - juga menghapus */. MySQL 5.6.31.
Franc Drobnič

10

Untuk solusi otomatis, Anda dapat melihat mysqlmigrate. Ini adalah pembungkus Bash mysqldumpyang memungkinkan Anda untuk memigrasi database dan mengabaikan pernyataan DEFINER. Contoh:

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

http://thesimplesynthesis.com/post/mysqlmigrate (atau GitHub )

Jika tidak, ya, perintah seperti yang ditunjukkan Abhay diperlukan:

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

6

Opsi lain di OSX untuk menghapus definisi dalam file:

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

5

Anda harus melihat jawabannya di sini: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

Cara terbaik menurut saya untuk mengatasi masalah ini, tidak menambahkan parse string ekstra dengan sed atau grep atau lainnya, sebaliknya mysqldump dapat menghasilkan dump yang baik dengan menambahkan --single-transaction


Mengapa suara negatif? Mengapa jawaban ini dianggap tidak berguna?
Jose Nobile

1
Tanggapan Anda masih membutuhkan sekitar 90 suara positif untuk mendapatkan posisi yang layak. Anda memiliki milik saya :)
Patrick van Bergen

4

Cara cepat untuk melakukan ini adalah dengan menyalurkan output dari mysqldump melalui sed untuk menghapus DEFINERpernyataan yang dibungkus dengan komentar bersyarat. Saya menggunakan ini untuk menghapus DEFINERdari CREATE TRIGGERpernyataan, tetapi Anda dapat mengubah nomor versi komentar kondisi di regex agar sesuai dengan tujuan Anda.

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

1
Pernyataan sed yang sedikit lebih mudah dibaca: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

Tidak yakin apakah itu membantu tetapi saya menggunakan SQLyog Community Edition, tersedia di: -

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

Saat membuang sql atau menyalin ke database lain, ini memungkinkan Anda untuk 'Abaikan DEFINER'

Ini gratis dan menyediakan fungsionalitas dasar yang dibutuhkan banyak orang

Ada juga versi berbayar yang tersedia dari: -

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

Bersulang


Daripada hanya menandakan sebagai 'tidak berguna' mungkin akan lebih berguna jika Anda membalas dengan mengapa Anda merasa itu tidak berguna?
itfidds

3

Bagi saya, ini bekerja: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. Ini menghapus DEFINER = root @ localhost dari dump saya, pada setiap pernyataan prosedur pembuatan


2

Berikut adalah solusi kerja lengkap untuk menghapus informasi DEFINER untuk MySQL 5.6.xdan Linux. (Diuji pada CentOS 6.5).

Biasanya kita harus mengganti entri berikut dari Mysql dump (jika diambil bersama dengan data dan pemicu / rutinitas / fungsi).

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

Dump diambil dengan perintah di bawah mysqldump.

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

File dump yang diperlukan tanpa informasi DEFINER dapat diperoleh dengan tiga perintah di bawah ini.

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

Jika file dump ada di folder Anda saat ini, abaikan [PATH /].

Jika data dalam tabel sangat besar maka ambil dump dalam dua file, di satu file dump ambil dump dengan data dan di file dump lainnya hanya mengambil dump dari skrip (Pemicu / Functions / Prosedur.) Dan menjalankan tiga di atas perintah pada file dump (skrip) ke-2.


1

Gantikan semua pengguna definer Anda dengan CURRENT_USER. Dalam skrip gradle saya yang membuat cadangan, skrip ganti saya terlihat seperti:

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

yang sebenarnya hanya memanggil ANT. Maka Anda tidak perlu khawatir tentang itu.


1

Di mesin Linux, Anda dapat menggunakan satu baris ini:

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

Anda hanya perlu mengganti string yang dicetak tebal dengan kredensial pengguna DB Anda dan nama database / pola suka.

Info lebih lanjut di sini: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

Satu-satunya cara saya bisa membuatnya bekerja di bawah Windows:

Instal http://gnuwin32.sourceforge.net/ agar sed di baris perintah dan tambahkan ke PATH Windows : D: \ program \ 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

Terima kasih atas petunjuknya. Karena malas, saya menulis skrip bernama: "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

Untuk sesuatu seperti:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNCTION `myfunction` () RETURNS int (11)
mulai
(...)
akhir ;;

Coba ini:

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

1
  1. buka database Anda dengan editor apa pun, saya gunakan dengan notepad ++,

  2. temukan semua uji itu DEFINER=root@localhost dan ganti dengan nothing ( "") IE. Hapus.

Kemudian Anda dapat mengimpornya ke host mana pun yang Anda inginkan.


0

Regex paling sederhana yang berfungsi untuk saya dengan semua objek adalah:

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

Perhatikan bahwa quote-namesharus TRUE(yang secara default).

Berharap bahwa di versi yang lebih baru, sakelar yang --skip-definerdiperkenalkan di mysqlpump di versi 5.7 juga datang ke mysqldump.


0

Saya telah menggunakan skrip PowerShell untuk menghapus semua baris DEFINER :

dapatkan-konten $ file_in_full_path | pilih-string-pola $ line_string_delete -notmatch | Out-File -width 1000000000 -Encoding Default $ file_out_full_path


0

Tidak ada yang berhasil untuk saya, jadi saya perlu menulis regex saya sendiri.

  1. Cobalah untuk membuang database Anda ke dalam file, catseluruh file dan grephanya pernyataan definer Anda yang dapat melihatnya.

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

  2. Tulis regex Anda

  3. Masukkan dump Anda ke sed dengan regex ini. Misalnya pernyataan saya adalah:

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

  4. Keuntungan!


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.