Изменить DEFINER для многих представлений

25

У меня проблемы с резервным копированием баз данных после обновления. Я копался в своей системе, пытаясь понять, почему. Один запрос, который я выполнил, дал этот результат

Got error: 1449: The user specified as a definer ('cittool'@'%') does not exist when using LOCK TABLES

После некоторого расследования выясняется, что определяющим для этих представлений является старая учетная запись разработчика, которая была удалена из системы. Базы данных и представления с этой проблемой используются очень редко, и большинство из них хранятся в архивных целях.

Существует около 40 просмотров с определителем, который больше не существует. Есть ли простой способ изменить определитель на другой аккаунт на все сразу? Есть ли способ заставить mysqldump просто выгрузить все представления в файл, чтобы я мог отредактировать этот файл и воссоздать представления?

Zoredache
источник
для меня я просто добавил отсутствующую учетную запись в базу данных, и ошибка исчезла.
user1794918

Ответы:

13

Создайте текстовый файл со всеми определениями вида:

mysql -uusername -ppassword -A --skip-column-names -e"SELECT CONCAT('SHOW CREATE VIEW ',table_schema,'.',table_name,'\\G') FROM information_schema.tables WHERE engine IS NULL" | mysql -uusername -ppassword -A --skip-column-names > AllMyViews.sql

Вы редактируете AllMyViews.sql оттуда. Затем бросьте взгляды

mysql -uusername -ppassword -A --skip-column-names -e"SELECT CONCAT('DROP VIEW ',table_schema,'.',table_name,';') FROM information_schema.tables WHERE engine IS NULL" | mysql -uusername -ppassword -A

После редактирования AllMyViews.sql перезагрузите их

mysql -uusername -ppassword -A < AllMyViews.sql

Попробуйте!

RolandoMySQLDBA
источник
+1 как отличная альтернатива, если view_definition of information_schema не отображается, но SHOW CREATE VIEW работает нормально.
Дерек Дауни
Хотя теоретически решение DTest мне нравилось больше, что-то в моей системе мешало его работе. Я в основном использовал вышеупомянутое, чтобы вывести операторы show create в файл, и мне пришлось немного их вручную отредактировать, а затем запустить.
Зоредаче
SHOW CREATE VIEW не работает, когда определенного пользователя не существует - он выдает ту же ошибку, что и mysqldump:The user specified as a definer ('abc'@'1.2.3.4') does not exist
Marki555
@ Marki555 Затем вы должны временно создать этого пользователя. бежать CREATE USER 'abc'@'1.2.3.4';. Затем попробуйте еще раз.
RolandoMySQLDBA
Я только что заметил, что представление использует некоторую хранимую процедуру и что сообщение об ошибке передается определителю этой процедуры, а не самому представлению
Marki555
25

Вы можете использовать ALTER VIEW в сочетании с информационной схемой . Вы упоминали, что выгрузили его в текстовый файл, так что, возможно, что-то вроде этого:

SELECT CONCAT("ALTER DEFINER=`youruser`@`host` VIEW `",table_name,"` AS ", view_definition,";") 
FROM information_schema.views WHERE table_schema='databasename'

Смешайте это с командной строкой mysql (при условии * nix, не знакомый с windows):

> echo "*abovequery*" | mysql -uuser -p > alterView.sql
> mysql -uuser -p databasename < alterView.sql

Sidenote: Вы не можете напрямую изменять записи в information_schema . Примечание 2: Это работает только для одной базы данных за раз, если вы не указали WHERE table_schema, вам нужно вставить команды USE между ними.

Дерек Дауни
источник
Мне нравится это, потому что это выглядит немного менее запутанным и более кратким, чем мой. +1 !!! (Я забыл про ALTER VIEW)
RolandoMySQLDBA
Любая идея, почему поле view_definition будет пустым? SELECT table_name,view_definition FROM information_schema.views WHERE table_schema='cittmp'; возвращается| Staff | |
Zoredache
Судя по обсуждению в чате, похоже, что это проблема разрешения с супер привилегией. bugs.mysql.com/bug.php?id=39733
Дерек Дауни
Идеальное решение! +1
Пабло Мартинес
По крайней мере, в RedHat, если вы выводите в файл, вы должны избегать обратных тиков, например,echo "SELECT CONCAT("ALTER DEFINER=\`youruser\`@\`host\` VIEW...
clav
3

Автоматизируя решение Дерека, это изменит DEFINER на root@localhostи установит SQL SECURITY INVOKER(убедитесь, что вы хотите это сначала!) Во всех представлениях во всех базах данных:

mysql -BNe 'show databases' | \
egrep -v '^(information_schema|performance_schema)$' | \
while read DB
do 
    mysql -BNe "SELECT CONCAT(\"ALTER DEFINER=\`root\`@\`localhost\` SQL SECURITY INVOKER VIEW \",table_name,\" AS \", view_definition,\";\") FROM information_schema.views WHERE table_schema=\"$DB\"" | \
    mysql $DB
done

ВНИМАНИЕ: убедитесь, что вы сделали полную резервную копию mysql (например, остановив mysqld и сделав резервную копию всех файлов в / var / lib / mysql), прежде чем запускать его - на всякий случай ... Это сработало для меня, но YMMV ,

Вы также должны проверить все ваши таблицы / представления с:

mysql -BNe 'show databases' | \
egrep -v '^(information_schema|performance_schema)$' | \
while read DB
do 
   mysql -BNe 'show tables' $DB | \
   while read t
   do
      echo "check table $t;"
   done | mysql -BN $DB
done | \
egrep -v 'status\s*OK'

он больше не должен жаловаться на недействительных определителей во взглядах.

Матия Налис
источник
Бесстыдно добавил это в мои фрагменты. Благодарность!
stefgosselin
3

Экспортировать все виды базы данных <DB>:

mysql -BNe "SELECT TABLE_NAME FROM TABLES WHERE TABLE_SCHEMA = '<DB>' AND TABLE_TYPE = 'VIEW'" \
    information_schema | xargs mysqldump --single-transaction --no-data <DB> >views.sql

или:

mysql -BNe "SELECT TABLE_NAME FROM VIEWS WHERE TABLE_SCHEMA = '<DB>'" \
    information_schema | xargs mysqldump --single-transaction --no-data <DB> >views.sql

Редактировать views.sql(изменить определитель) и воссоздать их:

cat views.sql | mysql <DB>

Укажите -uи -pпереключайте при необходимости.

х-юри
источник
Каким образом следует views.sqlредактировать VIEWS? Кроме того, как их воссоздать?
Шерил Хохман
@SherylHohman Изменить DEFINER = olduser@oldhostна DEFINER = newuser@newhost, cat views.sql | mysql <DB>воссоздает виды.
x-yuri