我开始怀疑自己——因为一条sql

文章讲述了在提供停车服务的系统中,流量误导向老服务导致支付问题。问题源于使用replaceINTO语句处理数据时,因主键冲突先删除再插入,使数据库字段type的默认值重置,进而影响服务。建议使用INSERT...ONDUPLICATEKEYUPDATE以避免类似问题。文章强调了冷静分析和深入理解技术的重要性。

故事是这样开始的

在一个月黑风高的夜晚

现场报过来,本该打到新服务的流量,又走到了老服务,老服务的功能不健全,很可能会让现场的用户不能支付。 需要说明一点的是,任何一个从老服务改造到新服务的时候,都不是完全把流量切过去,都需要经过一点时间去验证。

比如我们按照地理位置去切,将北京的部分车场(是的,我们是做停车服务的),切到新服务,其他城市的车场在老服务

我们采用最简单的办法,就是靠一个字段type去控制(0和1)

看似简单,但是事怪就怪在这个字段上,这个控制字段是属于后来加到数据库字段的,而且没有对外去配置,都是通过运维手动去数据库配置的,且数据库字段默认值设置为1。

可总有几个车场时不时的从0就变成了1。。众所周知,一个新的字段不在mybatis xml和pojo出现,那么就不会有操作改掉

翻遍所有的服务,关乎这个表的都是update操作,update操作因为没有这个字段时打死也不会改这个type的

冷静下来想想,数据库默认字段为1,然后0都会变成1。没有1变成0的,可以肯定的是,先删除,又新增了,否则没有别的解释

经过一番查验,找到这样一堆代码(伪代码)

replace INTO `A` (
      park_id,
      xxxx,
      xxxx
    )
    SELECT
       park_id,
       xxxx,
       xxxx 
    FROM
    B 
    where b.park_id = #{parkId}

复制代码

看到这里,心里嘿嘿一笑,破案了。。。。。

replace INTO

是的,就是replace INTO搞得鬼,大家都知道,replace INTO和insert into的区别

1、replace into 首先尝试插入数据到表中, 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据

2、如果表中无此数据,则插入新数据。

这就正好验证了上面的猜想,只有删除再添加,才会让type跟随数据库的默认值走

讲到这里不妨我们多了解一点这个,有人可能会问,replace是不是取代了insert和delete,毕竟是干了两件事

MySql手册关于replace into的算法:Mysql手册

MySQL uses the following algorithm for REPLACE (and LOAD DATA ... REPLACE):

Try to insert the new row into the table

While the insertion fails because a duplicate-key error occurs for a primary key or unique index:

Delete from the table the conflicting row that has the duplicate key value

Try again to insert the new row into the table



MySQL对REPLACE(和LOAD DATA…REPLACE)使用以下算法:

尝试将新行插入表中

当由于主键或唯一索引出现重复键错误而导致插入失败时:

从表中删除具有重复键值的冲突行

再次尝试将新行插入表中
复制代码

先插入, 出错了再执行delete加insert. 如果自己用程序来做, 个人认为效率会低很多,另外这样写真的很搞人

这里推荐使用INSERT...ON DUPLICATE KEY UPDATE, 感觉很靠谱. replace的副作用:

  • replace每次要重新分配自增id;

  • replace中执行delete时, 在有外键的情况下会很麻烦;

  • 如果delete时定义的有触发器, 则会被执行;

  • 副作用也会被传播到replica slave

总结

开发当中难免遇到奇奇怪怪的各种问题,有问题莫慌,冷静分析,你认为的不可能事件、你认为的计算机会发生错误,其实都是自己没有去完全理解到位,跟踪到位!!!

最后祝大家2023,少写bug,少加班,多涨薪

### 关于 SQL Server Service 和 SQL Service 配置与故障排除 #### 1. 检查 SQL Server 日志以定位问题 通过分析 SQL Server 的错误日志可以快速发现潜在的网络连接或其他配置相关的问题。可以通过 SQL Server Management Studio (SSMS) 打开并浏览这些日志文件,重点关注涉及网络通信的部分[^1]。 如果问题是关于 **Service Broker** 或者消息队列,则需要进一步检查是否有相关的异常记录。执行以下查询可以帮助找到可能存在的错误信息: ```sql SELECT * FROM ServiceBrokerException; ``` 此表存储了由 Service Broker 抛出的所有异常数据[^3]。 --- #### 2. 启动基于 Linux 的 SQL Server Agent 对于部署在 Linux 平台上的 SQL Server 实例,启动 SQL Server Agent 是一项常见需求。这通常涉及到修改 SQL Server 的配置设置来启用该服务。具体操作如下: 编辑 `/var/opt/mssql/mssql.conf` 文件,在其中添加或更新 `SQLAgent.Enabled=true` 参数,并保存更改。随后重启 SQL Server 服务使新配置生效[^2]。 注意:确保当前操作系统用户具有足够的权限访问上述配置文件以及管理服务状态的能力。 --- #### 3. 查询数据库是否已启用 Service Broker 功能 为了验证某个特定数据库(假设名称为 YourDatabaseName)是否支持 Service Broker 特性,可运行下面这条 T-SQL 命令: ```sql SELECT is_broker_enabled FROM sys.databases WHERE name = 'YourDatabaseName'; ``` 返回值为 `1` 表明已经激活;反之则未开启此项功能[^5]。如果没有被启用而计划使用它的话,请考虑重新创建目标数据库或者单独对其属性进行调整。 --- #### 4. 利用命令行工具确认 SQL Server 服务的工作状况 当怀疑存在底层的服务层面障碍时,借助 PowerShell 脚本或者其他终端指令能够迅速评估其健康度。例如,在 Windows 上可以输入以下语句获得即时反馈: ```powershell Get-Service | Where-Object {$_.DisplayName -like "*SQL*"} | Select Status, Name, DisplayName ``` 而在类 Unix 系统里则是采用 systemctl 方法完成相同目的: ```bash systemctl status mssql-server.service ``` 以上两种方式均能提供有关实例在线与否及其性能指标等方面的信息[^4]。 --- ### 总结 综上所述,针对 SQL Server services 及其关联组件遇到的技术难题可以从多个角度切入处理——从基础的日志审查到高级别的特性开关调节不等。每一步骤都紧密围绕着官方文档所推荐的最佳实践展开论述。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值