惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
月光博客
月光博客
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
小众软件
小众软件
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
博客园 - 三生石上(FineUI控件)
A
About on SuperTechFans
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
Vercel News
Vercel News
量子位
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
腾讯CDC
有赞技术团队
有赞技术团队

流动

山西之旅 | 流动 博客焕新,记录继续 | 流动 友链 | 流动 博客加速实践 广府古城一日游 我做了一个口播短视频二创工具:VideoRemaker Windows 下 Codex Cli 更新报 Move-Item is denied 错误的解决 Caddy 转发 GOST 报 TLS internal error 问题的排查与解决 对口型视频合成方案对比:Wav2Lip、VideoReTalking 与 MuseTalk 2026 音色克隆方案对比:IndexTTS-2、CosyVoice、GPT-SoVITS、Fish Speech、VoxCPM 部署与实测 AI Agent折腾记(OpenClaw / Hermes Agent) 我的2025年 大连之行 回家收麦 六一儿童节爬长城 Golang database/sql 数据库断线自动重连机制解析 Golang默认Http Client导致的cannot assign requested address错误 清明踏春,爬山看海 购入小牛G400T电动车 北京的三月飞雪 wrenAI本地LLM模型部署 天津一日游 2024年终总结 停止使用staticfile.org服务 使用 ImageMagick 自动添加水印,保护图片版权 如何注册一个.sol域名 奥森公园半日游 昌平42公里骑行绿道打卡 十月一日爬慕田峪长城 当Hugo遇上AVIF,优化图片加载
一次惊心动魄的Mysql更新操作
Liudon · 2020-05-19 · via 流动

问题描述

# 表结构
MySQL > desc user_packages;
+----------------+---------------------+------+-----+---------------------+----------------+
| Field          | Type                | Null | Key | Default             | Extra          |
+----------------+---------------------+------+-----+---------------------+----------------+
| up_id          | bigint(20) unsigned | NO   | PRI | NULL                | auto_increment |
| start_date     | date                | NO   |     | NULL                |                |
| end_date       | date                | NO   |     | NULL                |                |
| up_created     | datetime            | NO   | MUL | 0000-00-00 00:00:00 |                |
| up_updated     | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
+----------------+---------------------+------+-----+---------------------+----------------+
5 rows in set (0.00 sec)

MySQL > select * from user_packages limit 5;
+-------+------------+------------+
| up_id | start_date | end_date   |
+-------+------------+------------+
|   185 | 2018-04-01 | 2018-06-30 |
|   186 | 2018-04-01 | 2018-06-30 |
|   187 | 2018-04-01 | 2018-06-30 |
|   188 | 2018-04-01 | 2018-06-30 |
|   189 | 2018-04-01 | 2018-06-30 |
+-------+------------+------------+
5 rows in set (0.00 sec)

操作过程

需要更新某条记录的end_date字段,执行sql如下:

MySQL > update user_packages set end_date = '2020-06-06' and up_id = 189 limit 1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

执行完,发现sql写错了!!!!

正确的sql应该是:

update user_packages set end_date = '2020-06-06' where up_id = 189 limit 1;

误把where写成了and,还好指定了limit = 1,只操作了一条记录。

回滚

回滚的前提,要先找到更新的那条记录。

up_id为表的主键,更新前表里已经有这条记录了,主键不能重复,感觉语句应该没有执行成功。

MySQL > select * from user_packages where up_id = 189;
+-------+------------+------------+
| up_id | start_date | end_date   |
+-------+------------+------------+
|   189 | 2018-04-01 | 2018-06-30 |
+-------+------------+------------+
1 rows in set (0.00 sec)

执行查询语句,表里确实也只有这一条up_id=189的记录。

感觉这个update语句应该没执行成功,但是没执行成功应该报错的呀。

这个时候把希望放到了语句结果里的Warnings: 1,是不是没执行成功呢。

因为紧接着又执行了其他语句,所以也无法通过show warnings查看具体的错误信息了。

那么这条语句到底执行成功了吗?如果执行成功,那么修改的是哪条记录呢?

这里通过一番查找,终于定位到了记录。

AND分隔符,在mysql语句里优先级最高。

update user_packages set end_date = '2020-06-06' and up_id = 189 limit 1;

等效为

update user_packages set end_date = ('2020-06-06' and up_id = 189) limit 1;


update user_packages set end_date = 0 limit 1;

因为end_date字段为date类型,所以写入表后的记录为0000-00-00

MySQL > select * from user_packages where end_date = '0000-00-00';
+-------+------------+------------+
| up_id | start_date | end_date   |
+-------+------------+------------+
|   185 | 2018-04-01 | 0000-00-00 |
+-------+------------+------------+
1 rows in set (0.00 sec)

好在这次只更新了一条记录,否则后果无法想象。

切记不要在现网直接操作DB。

相关资料:

一个我认为是bug的UPDATE语句