java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist

来源:互联网 发布:新三板历年数据统计 编辑:程序博客网 时间:2024/04/28 21:17

在2014年的最后一个工作日,修改了生产环境中mysql的访问权限。
原来应用是以root身份访问数据库,现在给每个应用建了单独的用户访问数据库。
大约过去了两周,未见有异常。在反复确认了没有用root用户访问数据库后,决定彻底禁止root远程访问mysql。
在删除root@%用户后,发了一封邮件通知这件事情。

1分钟后悲剧开始,有人反映业务有问题。检查应用错误日志如下:
java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1160)

仔细检查发现数据库中有些trigger的definer是root@%,root@%用户被删除后,trigger找不到这些definer,就报错了。

mysql> SELECT
 t.TRIGGER_SCHEMA,     t.TRIGGER_NAME,
 t.EVENT_MANIPULATION, t.EVENT_OBJECT_SCHEMA,
 t.EVENT_OBJECT_TABLE, t.ACTION_TIMING, t.`DEFINER`
FROM  information_schema.`TRIGGERS` t where t.TRIGGER_SCHEMA='tion';
+----------------+------------------------------+--------------------+---------------------+--------------------+---------------+---------+
| TRIGGER_SCHEMA | TRIGGER_NAME                 | EVENT_MANIPULATION | EVENT_OBJECT_SCHEMA | EVENT_OBJECT_TABLE | ACTION_TIMING | DEFINER |
+----------------+------------------------------+--------------------+---------------------+--------------------+---------------+---------+
| tion           | orderUpdate_TRIGGER          | INSERT             | tion                | orderreply         | AFTER         |root@%  |
+----------------+------------------------------+--------------------+---------------------+--------------------+---------------+---------+


直接update  information_schema.`TRIGGERS` 返回ERROR 1044 (42000): Access denied
mysql> update information_schema.`TRIGGERS` set `DEFINER`='tion@%';
ERROR 1044 (42000): Access denied for user 'root'@'localhost' to database 'information_schema'

为了临时解决问题,直接通过工具SQLyog修改了tregger的definer,应用A的问题得到解决。

 

同时应用B,应用C也出现了异常.

应用B中有一条SQL执行时快时慢,有时还会超时,但总是没有返回结果。同事说:如果应用B中的SQL没返回结果,则应用C也不正常。


我们着重分析应用B的日志,除了偶尔超时,未见其他明显错误。我们开始去解决SQL执行时快时慢的问题。
SELECT * from information_schema.`PROCESSLIST` where info  is not null ;


看到有来自应用C的一些SQL执行时间异常,这时去执行应用B的SQL会很慢。

如果应用C的SQL执行完毕,执行应用B的SQL会很快。看来似乎找到了问题的原因。

是不是应用C有问题,因为应用C的SQL执行时间明显异常。(这个判断是从数据库的长期监控的结果得出的)

于是赶紧去看系统C的日志:
java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)

与系统A的错误十分相似。也是trigger中的definer引用了root@%这个用户。
原来应用A,B,C原来都是root用户访问Mysql。修改应用访问Mysql的权限后,分别使用了不同的用户。
但其中trigger的definer还是root,知道原因解决起来就比较简单了。

问题虽然解决了,但还是对生产照成了一定的影响。

这个事件再次提醒自己,生产环境的修改一定要谨慎,尤其是数据库,要有严谨的回退方案。

切不可以为操作简单,就可以大意。


根据这个事件引出的两个问题:

一、如何批量修改mysql中trigger的definer?

1.用mysqldump导出指定用户的trigger到文件
mysqldump -uroot -p   --triggers --add-drop-trigger --no-create-info --no-data --no-create-db --skip-opt   tion > triggers.sql

/*!50032 DROP TRIGGER IF EXISTS orderUpdate_TRIGGER */;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`%`*/ /*!50003 TRIGGER `orderUpdate_TRIGGER` AFTER INSERT ON `orderrep`

导出的文件中包括drop 和create trigger的语句,所以直接修改触发器的definer后直接导入就可以了。

2.修改导出文件中要修改trigger的definer

3.执行修改过的文件

 

二、怎么检查mysql中view,function,procedure,event,trigger的definer呢?
-- view
select table_name  ,view_definition,DEFINER FROM information_schema.views order by  definer ;


-- FUNCTION ,PROCEDURE
select  p.db ,p.`name` , p.type  , p.`definer` ,  p.created ,p.modified from  mysql.proc p  order by  definer ;

-- TRIGGER
SELECT t.TRIGGER_NAME,t.TRIGGER_SCHEMA ,t.EVENT_MANIPULATION ,t.EVENT_OBJECT_SCHEMA,t.EVENT_OBJECT_TABLE ,t.`DEFINER` from information_schema.`TRIGGERS`  t
ORDER BY t.`DEFINER`

-- EVENT
select e.EVENT_NAME,e.EVENT_SCHEMA , e.`DEFINER`  from information_schema.`EVENTS` e  order by  definer ;


解决生产中的问题时,保持一个清醒的头脑,平常心很重要。

0 0
原创粉丝点击