记一次mysql死循环的乌龙事件

问题描述

采购和接口对接的时候,因为沟通问题,导致采购提前放了问题数据订单进来,导致了两千多问题订单,还有七百多有效的问题订单,为了避免浪费,需要将这两千多有效的问题订单数据补全。

修复思路

订单表中数据缺失,用户表中有对应缺失信息。无法找回的信息固定写死一个值即可。

三种方式:

  • 最笨的:从日志中,找回数据,然后手动填充到db。
  • 正经开发人员:写一个程序,循环读取db,关联到乘客信息,然后将缺失的信息补充到订单表中即可。
  • 伟大的DBA:写个while循环,读取出来所有的问题订单数据,记录值,while的判断就是剩余问题订单数量大于0,处理方式是,取limit 0,1条数据,然后将数据的id拿出来,关联到用户表,将用户信息中的字段拿出来,反修改到订单表中。然后将总数值重新查一下,进入下一轮循环。循环结束后,问题订单应该是已经被全部修复了。

我当然选择伟大的DBA形式了,前两种对我来说so easy,但是费时费力,有dba经验的开发人员,还是想自我提升db功底的~

修复过程

首先来一个mysql的while循环格式,so easy,随手就来。写好了格式,按照思路来一套,先查出来订单总数,记录到变量中(尝试了一下,while循环好像不支持直接查询然后比较,也可能是我的语法错误,待会儿贴出代码,有问题的话,或者有改进方案,欢迎评论指责我,我们一同进步嘛)。进while循环判断,判断是否大于0,如果大于0,开始业务逻辑。先查出来limit 0,1条数据,拿到id保存到变量中,通过id去查用户信息,拿到用户信息里面的有用数据,保存到变量中。update订单表,根据id修改,将数据赋值过去(根据id,防止不小心修改多条)。再查一下目前的问题订单数,更新变量值,进入下一轮循环。

采坑记录

这么完美的逻辑怎么会还有坑呢!!!!!

问题记录

  • 首先运行,提示第一行有错误。单独运行的时候,第一行没问题,可以正常运行。
    • 将第一行提出来,用变量保存,while循环用变量判断,依然提示有问题
    • 将结束符修改一下,依然有问题。(知识点)
    • 将变量提前定义。还是不行。(知识点)
  • 百度发现,mysql的while循环只能放到存储过程中使用,无法单独执行。原谅我的无知,存储过程搞起!
    • 将脚本放到存储过程中,依然报错 - -!!,报第一行有sql问题。我的sql有问题,肯定是sql问题了,内部都可以执行,那就肯定出在while格式上面。
    • 百度mysql的while格式,一行一行,一个字母一个字母的比对,看看我的问题在哪,一个空格都不能少。最终发现第一行的格式一模一样,不会有错的呀。
    • 换一个思路,没有报错的也看一下,业务sql没问题,就不用看了,继续往下看。终于比对出问题,其他的end可以不加结束符,但是while的结束符需要加上结束符 ';'。真难受啊,还是太膨胀!终于找到问题了。

知识点

  • mysql的函数或者存储过程中,如果你要写多条sql一起执行,全部执行完z之后才需要结果的话,就需要将结束符修改一下。mysql的结束符是 ';',写存储过程的时候,每一条sql后面的结束符你都需要加上‘;’,这样的话,会导致一条sql执行完就整个结束了。为了避免这种情况,需要将结束符修改成其他的,全部结束后,再将结束符修改回来。
DELIMITER $$
BEGIN
.......
END $$
DELIMITER ;
  • 提前定义变量。我用的mysql5.7,这个版本我的测试结果是不支持提前定义变量的,网上很多的教程都说需要提前定义变量,版本不同吧,反正我用的版本,只要提前定义变量就会报错。在mysql5.7里面,常用的定义变量或者赋值的就两种,set @test = 11; 或者 select @test := 111; 如果使用 DECLARE COUNT INT DEFAULT 0; 这种方式,就会报错。可能也是我的语法有问题吧,但是目前为止,我还没有使用过提前定义正常的情况。如果使用提前定义的,然后报错了,不妨试一下,将提前定义的给去掉。我还没有去研究官方文档,后续研究之后再进行完善,目前也不能说的太肯定。
  • 如果sql编译器报错,说第一行出问题,不要相信他,一个语法中,相关联的,所有地方都有可能出错,仔细排查!
  • while 的end语句需要加上结束符,不加就会报错!

具体实现代码

重头戏来喽~最终的代码贴出来

CREATE DEFINER=`root`@`%` PROCEDURE `test`()
BEGIN
	select @ccc := count(1) from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0;

	WHILE  @ccc > 0 DO
		
		select @id := id from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0 limit 0,1;
		
		select @column1 := column1 , @column2 := column2 from table2 where orderid = @id;
		
		UPDATE table1 set column1 = @column1 , column2 = @column2 ,column3 = '2020-6-20' where id=@id;
		
		select @ccc := count(1) from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0;
	END WHILE;
END

-- 执行
CALL test();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写代码的喵o

请作者吃包辣条可好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值