运维与开发的开车现场之MySQL5.7创建触发器报错解决过程

报错内容如下:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5

内容概要

    作为一名运维小哥,先后经历了没有DBA的技术团队,有DBA的技术团队,然后又回到了没有DBA的技术团队。当开发人员提交SQL执行需求,运维人员进行SQL执行后,出现SQL报错。根据简单的报错信息大概能定位到时SQL语法的不严谨或者语法性问题,但单从sql层面上来讲,作为一个没有DBA的技术团队,经常使用SQL的也就是开发人员,运维人员更多时候是一个sql执行的角色,所以作为运维的我,因为不是专业的DBA,不能明确的指出开发人员SQL的缺陷。

    所以,当SQL执行出现问题,就变得有点意思了~

    下面,请允许我还原下开车现场:

说明

    企业所使用的服务器环境及服务等运维人员并没有全权掌控,确实存在不足。一部分是历史遗留原因;一部分是企业团队环境(企业在北京、上海、南京等多地设有子公司,致使有些东西难以做到全权统筹);同时作为运维小弟呢,光有一腔抱负,但却没有指点江山的职权,所以呢,有些事务确实难以推动。

    我呢,也只能在其位,谋其职,做好分内之事,同时,有时也会厚着脸皮跟老大说一些自己对于某些运维事务的处理方式、处理思路及运维环境等见解。至于是不是白说,我自己也不是很清楚^_^

    运维流程、运维事务处理方式的变更中的某些事务确实是牵一发而动全身,要改革,首先要自己能厚着脸皮说思想,其次要老大能心宽点头,接着要进行事务的推动(内容包括 运维与开发的对接信息内容、运维流程、事务处理手段等等),当中不仅需要坚定的劳苦付出,也存在着责任,存在着风险,即使说我来扛责任,但事实是我只是个微不足道的小角色,最终的担子会压在leader身上。不动没风险,只是机械劳作多点而已;而动了呢,动好了,在外行人眼里可能看不出来运维团队做的优化及其收益,提高了些许的工作效率,有些人也会觉得是理所应当。而动坏了,那就麻烦大了。所以当中的利弊,当中的难易,并非三言两语能说道明白。

    所以呢,目前还是墨守成规的进行着运维操作~~

报错:

环境

    a)运维团队及Leader在北京,我在上海负责相关上海的运维事务;

    b)测试环境MySQL全权开发掌管及自用,生产环境运维管理。

角色

    Me(运维,just me) Dev(开发) Cap(运维leader,我老大)

对白:

Me:Hi,你这SQL执行报错,语句有问题吧?

Dev:没有问题啊,我在测试环境执行都能成功的。

Me:但这确实是报错了啊,报错截图我给你了。

此刻空气凝固了10s左右 ~~~

Me:你这测试环境是怎么执行的?

Dev:用IDE工具。

Me:工具执行跟登陆数据库执行命令应该没区别吧,你这MySQL什么版本?

Dev:5.6

Me:生产环境是5.7,你确定不是版本差异导致的语法不兼容?

Dev:SQL没问题的,我本机的MySQL5.7执行都没问题。

Me:呃。。。那之前生产创建触发器出现这种情况咋处理的?

Dev:是Cap开启了数据库的某个全局权限,命令行执行SQL还是不行,但是我用IDE工具就成功了,所以之前是Cap开启全局权限,我这里执行。

Me:呃。。。那我问问。

Me:@Cap 老大,开发创建触发器的需求,需要开全局配置,之前我反映过开了那个可能会造成主从同步异常,所以上次你跟我说别随便开,那这次的需求咋处理?

Cap:先别开,你网上查查资料,处理下。

Me:好的,我琢磨下。。。

此刻我的内心读白:

    开发说SQL没问题,但是生产环境执行确实报错了,报错提示说的是版本差异或者SQL语法的问题,我觉得Dev在胡乱开车,奈何的是我却没有证据(因为自身SQL水平有限)~~

    好吧,硬着头皮找问题吧。

问题解决

    笔者通过问题排错,资料查询,并将数据导入到测试环境的MySQL5.7版本,然后进行相关的触发器创建SQL执行测试并多次修改试验,最后成功捕获问题并解决。

    以下是两种不同解决方案,前者是之前老大的修改全局配置权限的操作方式,后者是笔者的解决方式:

错误解决姿势

# 开启MySQL的某项权限

mysql > set global log_bin_trust_function_creators=1; 

# 权限开启后并给对应库的操作权限账号,由开发通过IDE工具执行SQL,操作成功!

# log_bin_trust_function_creators 参数说明:

    当二进制日志启用后,这个变量就会启用。它控制是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为0(默认值),用户不得创建或修改存储函数,除非它们具有除CREATE ROUTINE或ALTER ROUTINE特权之外的SUPER权限。 设置为0还强制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性声明函数的限制。 如果变量设置为1,MySQL不会对创建存储函数实施这些限制。此变量也适用于触发器的创建。

说明:

    那么为什么MySQL有这样的限制呢? 因为二进制日志的一个重要功能是用于主从复制,而存储函数有可能导致主从的数据不一致。同时经过实操后也确实出现了主从同步数据异常情况,所以,切勿轻易修改 log_bin_trust_function_creators 参数的默认值!

正确解决姿势

# 修改MySQL命令执行默认分隔符

说明:

    a)图中三部分红框内容为笔者添加;

    b)第一框是修改数据库默认的分隔符,指定为 " // " ;

    c)第二框是结束整条sql内容;

    d)第三框是将分隔符改回到默认;

    e)因sql语句中存在分号 ";" ,其用于整条sql内部的小断句,而MySQL默认的命令分隔符也是分号,故容易出现符号混淆,导致SQL执行异常。所以改变默认的命令行的分隔符用以区别分号,便能完美解决问题。

原文地址:https://www.cnblogs.com/kazihuo/p/11982271.html