当前位置:Gxlcms > 数据库问题 > mysql如何修改所有的definer

mysql如何修改所有的definer

时间:2021-07-01 10:21:17 帮助过:3人阅读

我们在mysql创建view、trigger、function、procedure、event时都会定义一个Definer=‘xxx’,类似如下:

  1. <span style="color: #0000ff;">CREATE</span><span style="color: #000000;">
  2. ALGORITHM </span><span style="color: #808080;">=</span><span style="color: #000000;"> UNDEFINED
  3. DEFINER </span><span style="color: #808080;">=</span> `root`@`<span style="color: #808080;">%</span><span style="color: #000000;">`
  4. </span> SQL SECURITY DEFINER
  5. <span style="color: #0000ff;">VIEW</span> `v_ questions` <span style="color: #0000ff;">AS</span>
  6. <span style="color: #0000ff;">SELECT</span><span style="color: #000000;">
  7. `q`.`id` </span><span style="color: #0000ff;">AS</span><span style="color: #000000;"> `id`,
  8. `q`.`title` </span><span style="color: #0000ff;">AS</span><span style="color: #000000;"> `title`
  9. </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;">
  10. Test q;
  11. 或者像这样的:
  12. </span><span style="color: #0000ff;">CREATE</span> DEFINER<span style="color: #808080;">=</span>`root`@`<span style="color: #808080;">%</span>` <span style="color: #0000ff;">PROCEDURE</span><span style="color: #000000;"> `user_count`()
  13. LANGUAGE SQL
  14. </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> DETERMINISTIC
  15. </span><span style="color: #0000ff;">CONTAINS</span><span style="color: #000000;"> SQL
  16. SQL SECURITY DEFINER
  17. COMMENT </span><span style="color: #ff0000;">‘‘</span>
  18. <span style="color: #0000ff;">BEGIN</span>
  19. <span style="color: #0000ff;">select</span> <span style="color: #ff00ff;">count</span>(<span style="color: #808080;">*</span>) <span style="color: #0000ff;">from</span> mysql.<span style="color: #ff00ff;">user</span><span style="color: #000000;">;
  20. </span><span style="color: #0000ff;">END</span>

 

加红的部分SQL SECURITY 其实后面有两个选项,一个为DEFINER,一个为INVOKER

SQL SECURITY { DEFINER | INVOKER } :指明谁有权限来执行。DEFINER 表示按定义者拥有的权限来执行

INVOKER 表示用调用者的权限来执行。默认情况下,系统指定为DEFINER 

 

以存储过程为例:

(1)MySQL存储过程是通过指定SQL SECURITY子句指定执行存储过程的实际用户;

(2)如果SQL SECURITY子句指定为DEFINER,存储过程将使用存储过程的DEFINER执行存储过程,验证调用存储过程的用户是否具有存储过程的execute权限和DEFINER用户是否具有存储过程引用的相关对象的权限;

(3)如果SQL SECURITY子句指定为INVOKER,那么MySQL将使用当前调用存储过程的用户执行此过程,并验证用户是否具有存储过程的execute权限和存储过程引用的相关对象的权限;

(4)如果不显示的指定SQL SECURITY子句,MySQL默认将以DEFINER执行存储过程。

 

 

我们来看下面几个小例子。

  1. <span style="color: #000000;">先授权一个:
  2. </span><span style="color: #0000ff;">grant</span> <span style="color: #808080;">all</span> <span style="color: #0000ff;">on</span> testdb.<span style="color: #808080;">*</span> <span style="color: #0000ff;">to</span> <span style="color: #ff0000;">‘</span><span style="color: #ff0000;">user1</span><span style="color: #ff0000;">‘</span>@<span style="color: #ff0000;">‘</span><span style="color: #ff0000;">%</span><span style="color: #ff0000;">‘</span> identified <span style="color: #0000ff;">by</span> <span style="color: #ff0000;">‘</span><span style="color: #ff0000;">000000</span><span style="color: #ff0000;">‘</span> <span style="color: #0000ff;">with</span> <span style="color: #0000ff;">grant</span> <span style="color: #0000ff;">option</span><span style="color: #000000;">;
  3. 然后我们创建一个存储过程如下:
  4. </span><span style="color: #0000ff;">USE</span><span style="color: #000000;"> `testdb`;
  5. </span><span style="color: #0000ff;">DROP</span> <span style="color: #0000ff;">procedure</span> <span style="color: #0000ff;">IF</span> <span style="color: #808080;">EXISTS</span><span style="color: #000000;"> `user_count`;
  6. DELIMITER $$
  7. </span><span style="color: #0000ff;">USE</span><span style="color: #000000;"> `testdb`$$
  8. </span><span style="color: #0000ff;">CREATE</span> DEFINER<span style="color: #808080;">=</span>`root`@`<span style="color: #808080;">%</span>` <span style="color: #0000ff;">PROCEDURE</span><span style="color: #000000;"> `user_count`()
  9. LANGUAGE SQL
  10. </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> DETERMINISTIC
  11. </span><span style="color: #0000ff;">CONTAINS</span><span style="color: #000000;"> SQL
  12. SQL SECURITY INVOKER
  13. COMMENT </span><span style="color: #ff0000;">‘‘</span>
  14. <span style="color: #0000ff;">BEGIN</span>
  15. <span style="color: #0000ff;">select</span> <span style="color: #ff00ff;">count</span>(<span style="color: #808080;">*</span>) <span style="color: #0000ff;">from</span> mysql.<span style="color: #ff00ff;">user</span><span style="color: #000000;">;
  16. </span><span style="color: #0000ff;">END</span><span style="color: #000000;">$$
  17. DELIMITER ;</span>

 

 

用root帐号登陆:

  1. mysql<span style="color: #808080;">></span> <span style="color: #0000ff;">use</span><span style="color: #000000;"> testdb;
  2. </span><span style="color: #0000ff;">Database</span><span style="color: #000000;"> changed
  3. mysql</span><span style="color: #808080;">></span><span style="color: #000000;"> call user_count();
  4. </span><span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  5. <span style="color: #808080;">|</span> <span style="color: #ff00ff;">count</span>(<span style="color: #808080;">*</span>) <span style="color: #808080;">|</span>
  6. <span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  7. <span style="color: #808080;">|</span> <span style="color: #800000; font-weight: bold;">3</span> <span style="color: #808080;">|</span>
  8. <span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  9. <span style="color: #800000; font-weight: bold;">1</span> row <span style="color: #808080;">in</span> <span style="color: #0000ff;">set</span> (<span style="color: #800000; font-weight: bold;">0.00</span><span style="color: #000000;"> sec)
  10. Query OK, </span><span style="color: #800000; font-weight: bold;">0</span> rows affected (<span style="color: #800000; font-weight: bold;">0.00</span><span style="color: #000000;"> sec)
  11. 可以正常查询出来。
  12. 我们再用user1进行登陆:
  13. mysql</span><span style="color: #808080;">></span> <span style="color: #0000ff;">use</span><span style="color: #000000;"> testdb;
  14. </span><span style="color: #0000ff;">Database</span><span style="color: #000000;"> changed
  15. mysql</span><span style="color: #808080;">></span><span style="color: #000000;"> call user_count();
  16. ERROR </span><span style="color: #800000; font-weight: bold;">1142</span> (<span style="color: #800000; font-weight: bold;">42000</span>): <span style="color: #0000ff;">SELECT</span> command denied <span style="color: #0000ff;">to</span> <span style="color: #ff00ff;">user</span> <span style="color: #ff0000;">‘</span><span style="color: #ff0000;">user1</span><span style="color: #ff0000;">‘</span>@<span style="color: #ff0000;">‘</span><span style="color: #ff0000;">localhost</span><span style="color: #ff0000;">‘</span> <span style="color: #0000ff;">for</span> <span style="color: #0000ff;">table</span> <span style="color: #ff0000;">‘</span><span style="color: #ff0000;">user</span><span style="color: #ff0000;">‘</span>

 

发现系统报错查询不到了,这是因为我们在上述定义的SQL SECURITY值为INVOKER,存储过程执行过程中会以user1具有的权限来执行,其中调用到了mysql的库,而我们的user1帐户只有testdb库的使用权限,所以会返回失败。

 

我们把上面的invoker改为definer再来试一下:

  1. <span style="color: #0000ff;">update</span> mysql.<span style="color: #0000ff;">proc</span> <span style="color: #0000ff;">set</span> security_type<span style="color: #808080;">=</span><span style="color: #ff0000;">‘</span><span style="color: #ff0000;">DEFINER</span><span style="color: #ff0000;">‘</span> <span style="color: #0000ff;">where</span> db<span style="color: #808080;">=</span><span style="color: #ff0000;">‘</span><span style="color: #ff0000;">testdb</span><span style="color: #ff0000;">‘</span> <span style="color: #808080;">and</span> name<span style="color: #808080;">=</span><span style="color: #ff0000;">‘</span><span style="color: #ff0000;">user_count</span><span style="color: #ff0000;">‘</span><span style="color: #000000;">;
  2. 再次用user1进行登陆:
  3. mysql</span><span style="color: #808080;">></span> <span style="color: #0000ff;">use</span><span style="color: #000000;"> testdb;
  4. </span><span style="color: #0000ff;">Database</span><span style="color: #000000;"> changed
  5. mysql</span><span style="color: #808080;">></span><span style="color: #000000;"> call user_count();
  6. </span><span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  7. <span style="color: #808080;">|</span> <span style="color: #ff00ff;">count</span>(<span style="color: #808080;">*</span>) <span style="color: #808080;">|</span>
  8. <span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  9. <span style="color: #808080;">|</span> <span style="color: #800000; font-weight: bold;">3</span> <span style="color: #808080;">|</span>
  10. <span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">--------+</span>
  11. <span style="color: #800000; font-weight: bold;">1</span> row <span style="color: #808080;">in</span> <span style="color: #0000ff;">set</span> (<span style="color: #800000; font-weight: bold;">0.00</span><span style="color: #000000;"> sec)
  12. Query OK, </span><span style="color: #800000; font-weight: bold;">0</span> rows affected (<span style="color: #800000; font-weight: bold;">0.00</span> sec)

 

 

发现可以查询出来了,因为user1对存储过程user_count有执行的权限,虽然它依旧没有权限直接操作mysql库,由于我们定义的SQL SECURITY为DEFINER,所以在执行时是以root的身份执行的,所以可以正常查询出来。

 

如果方便修改mysql中所有已经定义到的definer?

由于前期在测试库上开发的缘故,我们经常定义到的definer为`root`@`%`,后来搬移到生产库上又得改回来,存在着大量的更新,上百个的视图,函数等一个个改不免太麻烦并且也可能遗漏。如下为总结出的方便修改所有definer的方法,可以直到查漏补缺的作用。

现在在mysql涉及的definer有view、trigger、function、procedure、event。我们一个个作介绍。

1.修改function、procedure的definer

select definer from mysql.proc;  -- 函数、存储过程

update mysql.proc set definer=‘user@localhost‘; -- 如果有限定库或其它可以加上where条件

 

2.修改event的definer

select DEFINER from mysql.EVENT; -- 定时事件

update mysql.EVENT set definer=‘ user@localhost ‘;

 

3.修改view的definer

相比function的修改麻烦点:

select DEFINER from information_schema.VIEWS; 

select concat("alter DEFINER=`user`@`localhost` SQL SECURITY DEFINER VIEW ",TABLE_SCHEMA,".",TABLE_NAME," as ",VIEW_DEFINITION,";") from information_schema.VIEWS where DEFINER<>‘user@localhost‘; 

查询出来的语句再执行一遍就好了。

 

4.修改trigger的definer

目前还没有具体方便的方法,可以借助工具端如HeidiSQL、sqlyog等来一个个修改。注意改前有必要锁表,因为如果改的过程中有其它表改变而触发,会造成数据不一致。

Flush tables with readlock

Unlock tables

 

如果有找到方法的方法,记得留言,相互学习。

mysql如何修改所有的definer

标签:

人气教程排行