MySQL导入的时候1127的错误
nanshan 2025-01-05 19:19 12 浏览 0 评论
关注我「程序猿集锦」,获取更多分享。
- 背景
- 排查原因
- 错误提示一的原因
- definer
- invoker
- 错误提示二的原因
- log_bin_trust_function_creators
- 解决方案
- 错误提示一的方案
- 方案一
- 方案二
- 错误提示二的方案
- 总结
背景
在AWS RDS环境下,使用mysqldump备份了一个MySQL数据库数据库,然后想把它用mysql的命令还原到另外一个数据库下面,结果在还原的过程中遇到的下面的错误提示信息,此时的MySQL实例是没有开启binlog。
ERROR 1227 (42000) at line 1163: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
如果在开启了binlog的情况下,把mysqldump命令备份的SQL文件导入到新的schema下面,则会出现如下的错误提示:
ERROR 1419 (HY000) at line 1163: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
下面研究了一下出现上面两个错误的原因分别是什么。
排查原因
错误提示一的原因
先看第一个错误是什么原因导致的
根据第一个错误提示信息,我找到了导出来的SQL文件的第1163行,发现这一行的代码如下所示,在这一行定义了一个trigger触发器。
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`app_user`@`10.10.%`*/ /*!50003 trigger SEC_RESOURCE_ROLE_DELETE_TS_NN_UPDATE_TRIGGER before update on SEC_RESOURCE_ROLE
for each row
begin
if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then
set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS);
end if;
end */;;
DELIMITER ;
根据错误提示信息,再加上定位到的SQL语句,我猜测是当前我执行导入操作的用户,没有权限吗?
为了验证我的猜测,我把同样的SQL文件,在本地的MySQL数据库中,使用root用户导入了一次,结果成功了。而使用了AWS RDS for MySQL的管理员用户想RDS中导入却失败,确实是这个权限的问题。
我们都知道AWS RDS中的用户是没有root权限的,但是没有想到它的权限是这么低。RDS中权限最大的用户就是这个了,如果这个权限都不够的话,那就没有任何其他用户可以用了。只能继续想办法看下具体是需要什么样的权限才可以执行上面的创建触发器的语句。
我把上面创建触发器的SQL语句,稍做修改,发现把里面的DEFINER选项/*!50017 DEFINER=app_user@10.10.%*/给去掉就可以创建成功。改为如下的语句来执行是OK的:
DELIMITER ;;
/*!50003 CREATE*/ /*!50003 trigger SEC_RESOURCE_ROLE_DELETE_TS_NN_UPDATE_TRIGGER before update on SEC_RESOURCE_ROLE
for each row
begin
if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then
set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS);
end if;
end */;;
DELIMITER ;
这说明是definer的语句导致了上面的触发器不能正常在MySQL版本的RDS中执行。
在MySQL中,创建函数、存储过程、视图、事件、触发器的时候,可以为其指定definer属性,但是只能指定执行当前创建函数、存储过程、视图、事件、触发器对象DDL语句的用户才可以,如果要指定为其他用户作为definer,则需要使用超级用户才可以。
definer
这里说明一下definer关键字的作用。
definer关键字的作用是用来指定当前的函数、存储过程、视图、事件、触发器等数据库对象是由哪个用户创建的。这里在指定的时候可以为某一个数据库对象指定其他用户作为definer,但前提是拥有super权限的用户才可以在创建数据库对象的时候指定其他用户作为definer,非super权限的用户,不可以这么做,只能指定它自己作为definer。如果在创建对象的时候没有显示的声明definer,会用当前执行创建对象DDL语句的用户来作为默认的definer。
如下是定义了definer的存储过程p1的示例。它使用了SQL SECURITY DEFINER属性,并且指定了definer为u3@%这个用户,存储过程里面是对数据库procedure_test下面的表t1的counter字段执行加1的一个update操作。也就是说,这个存储过程p1每被调用一次,数据库procedure_test下面的表t1的counter字段的值就会被加1。
use procedure_test;
delimiter ;;
CREATE DEFINER = 'u3'@'%' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
UPDATE procedure_test.t1 SET counter = counter + 1;
END;;
delimiter ;
/*上面的存储过程,等价于下面的存储过程*/
use procedure_test;
delimiter ;;
CREATE DEFINER = 'u3'@'%' PROCEDURE p1()
-- SQL SECURITY DEFINER /*可以省略该行,不指定的时候,默认就是使用sql security definer*/
BEGIN
UPDATE procedure_test.t1 SET counter = counter + 1;
END;;
delimiter ;
对于上面的存储过程p1,不管调用这个存储过程的用户是否对procedure_test数据库下面的表t1是否有select、update的权限(注意:修改一个表,前提是可以查询表中的数据,查询出来后才可以修改,所以不仅仅需要update的权限,还需要select的权限),只要这个用户在procedure_test数据库下面有EXECUTE的权限,这个用户就可以调用procedure_test数据库下面的p1这个存储过程。
它是以definer中指定的用户u3@%来执行这个存储过程中的命令的。如果definer中定义的用户u3@%对存储过程中使用的数据库对象procedure_test.t1没有对应的select、update的权限,那么这个调用存储过程p1的用户在以definer用户u3@%去调用该存储过程的时候,也会失败。
invoker
说道了definer属性,就要提一下invoker属性。
在定义函数、存储过程、视图对象的时候,除了可以指定definer属性之外,还可以为其指定invoker属性。invoker属性的含义是,哪个用户可以调用这个数据库对象。
当前一个对象没有在begin前面显示的声明SQL SECURITY DEFINER或SQL SECURITY INVOKER的时候,默认是使用SQL SECURITY DEFINER。当一个对象显示的声明了SQL SECURITY INVOKER则会覆盖definer属性的定义,真正在执行对应的对象的时候,会按照invoker的权限去判断是否可以执行对应的命令。
如下是一个定义了invoker的存储过程p2。这个存储过程,和前面不同的是,这里使用了SQL SECURITY INVOKER属性。
use procedure_test;
delimiter ;;
CREATE DEFINER = 'u3'@'%' PROCEDURE p2()
SQL SECURITY INVOKER
BEGIN
UPDATE procedure_test.t1 SET counter = counter + 100;
END;;
delimiter ;
对于上面的存储过程p2,虽然定义的时候指定了definer为u3@%,但是由于还指定了SQL SECURITY INVOKER,所以在这个存储过程被调用的时候,会根据invoker的属性去判断是否可以成功调用该存储过程,忽略definer属性的约束。这个存储过程p2是否可以调用成功,取决于调用者是否对数据库procedure_test下面的t1表拥有select、update的权限。不会判断调用者对数据库procedure_test是否有execute权限。
**注意:**触发器、事件这两个对象是没有invoker属性,不能为其指定哪些用户可以调用执行它们,它们的调用执行由MySQL自己决定什么时候调用,最多只能为其指定definer属性,标识是哪个用户创建的触发器、事件。其他的几个像:存储过程、函数、视图是可以为其指定invoker属性的,标识哪个用户可以调用该对象。
错误提示二的原因
接下来我们再看第二个错误是什么原因导致的。
根据错误二的提示信息,我尝试使用root用户在我本地的MySQL中执行导入操作,在开启binlog的情况下,是可以导入成功的。但是如果使用一个非root用户,在本地MySQL开启binlog的情况下, 导入确实会出现下面的错误提示:
ERROR 1419 (HY000) at line 1163: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
错误提示给出了关键的解决方式:那就通过参数log_bin_trust_function_creators的配置可以解决这个问题。
log_bin_trust_function_creators
该参数只有在binlog开启的情况下才会生效,如果binlog没有开启,这个参数不管配置成什么值,都不会生效,不起任何作用。所以,接下来我们讨论的这个参数配置为off或者on的前提是:binlog已经是开启的状态。
参数log_bin_trust_function_creators的取值范围是0或1,对应着off或者on,其默认值为off。它是用来控制MySQL是否信任函数、存储过程、触发器的创建者所创建的这些数据库对象。
- off,表示不信任。在创建函数、存储过程、触发器之前,MySQL会验证这些对象是否可以被创建。
- on,表示信任。在创建函数、存储过程、触发器之前,MySQL不会去验证这些对象是否可以被创建,待创建的对象只要语法上没有问题,就可以创建成功。
那么参数log_bin_trust_function_creators到底是对待创建的数据库对象(function、procedure、trigger)做什么验证呢?
如果待创建的数据库对象,在定义过程中引用了非确定性因素的函数事件,比如在SQL语句中引用了rand()、uuid()、now()等MySQL内置的函数,就认为这个待创建的数据库对象是不安全的。因为每次调用或执行这个数据库对象后,它所产生的结果是不确定的。此时MySQL就认为这个对象是安全的数据库对象。
- 如果参数log_bin_trust_function_creators=off的时候,MySQL就会对待创建的数据库对象进行上面我们描述的检查和验证。是安全的对象,则可以创建成功,如果是不安全的对象则不能创建成功(拥有超级权限的用户除外,超级权限的用户在log_bin_trust_function_creators=off的情况下,即便是非安全的数据库对象,也可以创建成功)。会抛出一个异常信息如下:
ERROR 1419 (HY000) at line 1163: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
- 如果参数log_bin_trust_function_creators=on的时候,MySQL就不会对待创建的数据库对象进行安全性的检查,在语法没有错误的前提下,可以直接创建成功。
题外话:为什么说引用rand()、uuid()、now()等不确定结果函数的数据库对象就是不安全的呢?
这要从MySQL数据库binlog和主从复制说起。
我们知道在binlog开启的情况下,我们对数据库中数据的任何变更操作都会被记录在binlog中,从库在同步主库的数据的时候,就是读取主库中binlog的记录,然后再从库在执行一遍,来达到从库数据库和主库数据一致的要求。
但是如果我们调用或执行一些数据库对象的时候,它们引用了MySQL内置的不确定性的函数如uuid()。那么binlog中记录的这个操作的SQL语句在不同的MySQL实例上重放的时候,将会得到不同的结果。
例如一个存储过程中对某个表的某一行进行了修改,其语句为update t set a=uuid() where id = 1;。那么在binlog的记录格式是statement格式的时候,binlog中就会记录这样的一个SQL语句,并不是把调用uuid()之后的得到的数据行修改后的内容记录在binlog中。那么这样的binlog在同步到从库之后,从库重放binlog中的这样的记录时,在从库上执行的update t set a=uuid() where id = 1;这个SQL语句后的结果得到的uuid()的值,和主库上的值是相同的可能性几乎为零。这就导致了从库上面id=1的数据行,和主库上面id=1的数据行的内容不一致,进而可能导致主从同步中断。这就是为什么引用不确定性内置函数的数据库对象被视为不安全的原因。
如果在binlog格式是row格式的情况下,就不会出现上面我们描述这样因为不安全的内置函数引用而导致的主从数据不一致的情况,因为row格式的binlog记录的是id=1这一行数据修改后的数据内容,这样的binlog在从库中重放的时候,就直接把修改后的数据内容应用到从库上,而不是把在主库上执行是SQL语句在从库上重新执行一遍。所以,在binlog开启并且格式为row的前提下,即便是把参数log_bin_trust_function_creators=on,表示在创建数据库对象的时候不做验证,也不会导致主从数据不一致的问题。
如果开启了binlog之后并且搭建了主从,同时binlog的格式为statement,参数log_bin_trust_function_creators改为on之后,表示不会对函数、存储过程、触发器等对象在创建的时候,进行验证它们的安全性。就很有可能导致主从数据不一致。
当然,如果没有开启binlog,或者开启了binlog但没有配置主从同步,只是一个单实例的MySQL服务,设置这个参数为on,不会导致主从不同步。但是如果开启了binlog,并且格式为statement,在使用binlog做数据恢复还原的时候,也是有可能导致还原后的数据和原先的数据不一致。所以,只要开启了binlog,格式请一定设置为row格式。
对于binlog开启与否,以及binlog的格式,主从链路的状态和log_bin_trust_function_creators参数之间的影响关系如下:
序号 | binlog状态 | binlog格式 | 主从链路状态 | log_bin_trust_function_creators状态 | 对主从或使用binlog恢复数的影响 |
1 | ON | row | ON | ON/OFF都可以 | 无 |
2 | ON | row | OFF | ON/OFF都可以 | 无 |
3 | ON | mixed | ON | ON/OFF都可以 | 无 |
4 | ON | mixed | OFF | ON/OFF都可以 | 无 |
5 | ON | statement | ON | ON | 有 |
6 | ON | statement | OFF | ON/OFF都可以 | 无 |
7 | OFF | N/A | N/A | ON/OFF都可以 | 无 |
解决方案
错误提示一的方案
了解了definer和revoker的作用之后,根据MySQL给抛出来的错误信息,结合AWS RDS版本的MySQL用户是没有超级用户的权限的,我们就可以理解为什么使用mysqldump导出来的创建触发器的语句会带有definer,并且也能理解为什么导入到新的schema下面就不能导入的原因了。
理解了为什么,我们就可以针对性的进行解决这个问题了。目前的解决方案有以下几种:
方案一
因为AWS RDS版本的MySQL用户没有超级权限,不能指定definer为其他用户,所以我们可以把这个definer定义给删除掉。这样在导入的时候,就会默认使用当前执行导入的用户来作为该触发器的definer。
如果你导出来的SQL文件比较小,可以直接双击打开编辑或者使用vi命令来编辑,找到对应的definer定义,将其删除。
如果你导出来的SQL文件比较大,双击打开或者使用vi命令编辑基本不可能,那么就使用如下的sed语句可以将函数、存储过程、视图、事件、触发器中的definer属性给删除掉。在使用sed命令之前,请先备份你的原来的SQL文件,避免删除失败后,不能恢复。
cp your_mysqldump_file.sql your_mysqldump_file.sql.bak
sed -i -e 's/DEFINER=`app_user`@`10.10.\%`//g' your_mysqldump_file.sql
方案二
由于AWS RDS版本的MySQL提供的用户,没有超级权限,所以它不能创建入触发器的时候,指定其他用户作为definer,那么我们可以将dump出来的SQL文件中的definer改为当前RDS提供的用户。同样需要备份源SQL文件,给自己留个后悔药吃。
cp your_mysqldump_file.sql your_mysqldump_file.sql.bak
sed -i -e 's/DEFINER=`app_user`@`10.10.\%`/DEFINER=`your_rds_admin_user`@`\%`/g' your_mysqldump_file.sql
这样修改后的SQL文件,就可以使用RDS提供的用户导入到新的schema下面了。
这里在替换为RDS admin的用户的时候,需要注意,用户名称后面是需要跟上%还是跟上具体的某一个网段,则需要根据你的mysql.user表中定义的RDS admin用户对应的host列中的值是什么。一般情况下面,RDS提供的admin用户他们的网段都是%,而不是具体的某一个网段。
错误提示二的方案
目前我的RDS版本的MySQL是开启了binlog,并且binlog的格式是row格式,但是我没有配置主从同步的链路。所以,我们要修复前面开始遇到的问题,只需要把参数log_bin_trust_function_creators由原先默认的off改为on,来开启信任函数的创建者就可以避免创建触发器、存储过程等数据库对象的验证了。
修改参数的操作如下:
mysql> set global log_bin_trust_function_creators = on;
Query OK, 0 rows affected (0.00 sec)
修改完成上面的参数后,再重新导入SQL文件,即便是里面有触发器、函数的创建,也可以创建成功了。不会对这些将要创建的触发器、函数、存储过程进行安全性的检查了。
但是如果需要这个参数长时间生效,需要在MySQL的参数配置文件中增加这个参数的配置。自己安装部署的MySQL服务,可以修改my.cnf配置文件,如果是RDS版本的MySQL,则需要修改参数组中的这个参数,找到对应的参数,修改后,保存既可以,如果是多个RDS实例,使用同一个参数组,则需要复制出来一份新的参数组来给当前需要修改参数的RDS来使用。为了让新的参数组生效,则需要重启MySQL的RDS服务。
总结
这里简单总结一下这篇文章的内容。
这里,我们主要分析了MySQL中创建函数、存储过程、触发器中时候,定义者definer和调用者invoker的使用规则,它们用来控制MySQL数据库中函数、存储过程、触发器等数据库对象的被调用的时候,哪些用户可以调用它们。
同时,还分析了参数log_bin_trust_function_creators的作用,它用来控制在MySQL中创建函数、存储过程、触发器等数据库对象的时候,是否会对这些待创建的数据库对象进行数据安全性的检查。
关注我「程序猿集锦」,获取更多分享。
- 上一篇:MySQL操作命令指南(MySQL命令速查)
- 下一篇:MySQL 日志管理
相关推荐
- 0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)
-
文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...
- ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes
-
为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...
- 生产环境starrocks 3.1存算一体集群部署
-
集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...
- 在CentOS上添加swap虚拟内存并设置优先级
-
现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...
- 国产深度(deepin)操作系统优化指南
-
1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...
- postgresql-15.4 多节点主从(读写分离)
-
1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...
- Docker 容器 Java 服务内存与 GC 优化实施方案
-
一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...
- 虚拟内存设置、解决linux内存不够问题
-
虚拟内存设置(解决linux内存不够情况)背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...
- Elasticsearch性能调优(5):服务器配置选择
-
在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...
- Es如何落地
-
一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...
- 针对Linux内存管理知识学习总结
-
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...
- MySQL进阶之性能优化
-
概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...
- Linux Cgroups(Control Groups)原理
-
LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...
- linux 常用性能优化参数及理解
-
1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...
- 如何在 Linux 中使用 Sysctl 命令?
-
sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)