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?

FastTrack
sumber
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
Abhay
sumber
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
Ricardo Martins
sumber
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

maxhb
sumber
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

SitesBySequoia.com
sumber
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
Jonathan
sumber
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=[^ ]* / /'
Lajos Veres
sumber
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
josephdpurcell.dll
sumber
6

Opsi lain di OSX untuk menghapus definisi dalam file:

sed -i '' 's/DEFINER=`[^`][^`]*`@`[^`][^`]*`//g' file.sql
mohrt
sumber
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

Jose Nobile
sumber
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=`.*`@`.*`\*\///' 
Paul Dixon
sumber
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

itfidds
sumber
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

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

I Bajwa PHD
sumber
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.

Ryan Shillington
sumber
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/

Novoj
sumber
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
Artur Kędzior
sumber
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
R. Canaro
sumber
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'
impactaweb
sumber
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.

Lê Công Danh
sumber
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.

Franc Drobnič
sumber
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

Alen
sumber
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!

Xdg
sumber
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
Luiz Rodolfo
sumber