千家信息网

MySQL危险而诡异的update操作和惊魂5分钟

发表于:2024-11-29 作者:千家信息网编辑
千家信息网最后更新 2024年11月29日,MySQL危险而诡异的update操作和惊魂5分钟简介Part1:写在最前上班正忙的不可开交呢,一个消息过来,得知研发人员误操作数据库了....不带where条件,整表更新Orz,还让不让人好好活了,
千家信息网最后更新 2024年11月29日MySQL危险而诡异的update操作和惊魂5分钟

MySQL危险而诡异的update操作和惊魂5分钟

简介

Part1:写在最前

上班正忙的不可开交呢,一个消息过来,得知研发人员误操作数据库了....不带where条件,整表更新Orz,还让不让人好好活了,心中一万只XXX啊~无奈,分清事情的轻重,优先处理这起事故。

在简单沟通后,了解到事故的原因是研发人员使用update忘记带where条件。这本身没什么诡异的,诡异的是在决定要不要进行恢复的时候,笔者稍微犹豫了一下,因为看起来是不需要恢复的,那么具体是什么样的情况呢?


Part2:危险场景再现


研发人员update使用了错误的语法,本意是update helei3 set a='1' where b='a';

结果写成了update helei3 set a='1' and b='a';

这样的话使得helei3这张表的a列被批量修改为0或1。

过了几秒钟,发现写错并且已经敲了回车后,此时update语句还没有更新完,立即ctrl+c

那么数据到底有没有被写脏?


复现

Part1:创建所需表

首先我们创建测试表,a列b列均为varchar类型

root@127.0.0.1 (helei)> show create table helei3\G*************************** 1. row ***************************       Table: helei3Create Table: CREATE TABLE `helei3` (  `a` varchar(10) DEFAULT NULL,  `b` varchar(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

表中数据如下

root@127.0.0.1 (helei)> select * from helei3;+------+------+| a    | b    |+------+------+| 1    | a    || 2    | b    || 3    | c    |+------+------+3 rows in set (0.00 sec)


Part2:错误语句生成

我们都知道,update的语法是update tablename set col1=val,col2=val2 where xxx;

那么当逗号换成了and,会出现什么样的严重后果呢?


这个时候由于没有where条件,导致整表更新,那猜猜看后续结果是什么

root@127.0.0.1 (helei)> update helei3 set a='1' and b='a';root@127.0.0.1 (helei)> select * from helei3;+------+------+| a    | b    |+------+------+| 1    | a    || 0    | b    || 0    | c    |+------+------+4 rows in set (0.00 sec)

没错,这个SQL将a列整表更新为0,而之所以第一个a=1是由于a='1' and b='a'这个条件是真,所以为1。


Part3:ctrl+c

了解Part2后,我们再看下当update全表更新发现误操作后立即ctrl+c能不能回滚避免误操作。

提前准备好一张50万数据的表

root@127.0.0.1 (helei)> select count(*) from helei;+----------+| count(*) |+----------+|   500000 |+----------+1 row in set (0.06 sec)root@127.0.0.1 (helei)> show create table helei\G*************************** 1. row ***************************       Table: heleiCreate Table: CREATE TABLE `helei` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `c1` int(10) NOT NULL DEFAULT '0',  `c2` int(10) unsigned DEFAULT NULL,  `c5` int(10) unsigned NOT NULL DEFAULT '0',  `c3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  `c4` varchar(200) NOT NULL DEFAULT '',  PRIMARY KEY (`id`),  KEY `idx_c1` (`c1`),  KEY `idx_c2` (`c2`)) ENGINE=InnoDB AUTO_INCREMENT=500001 DEFAULT CHARSET=utf8mb41 row in set (0.00 sec)


误操作整表更新后等待几秒立即ctrl + c

root@127.0.0.1 (helei)> update helei set c2=1;^CCtrl-C -- sending "KILL QUERY 2133" to server ...Ctrl-C -- query aborted.^CCtrl-C -- sending "KILL 2133" to server ...Ctrl-C -- query aborted.ERROR 2013 (HY000): Lost connection to MySQL server during queryroot@127.0.0.1 (helei)> select * from helei where c2=1;Empty set (0.00 sec)


可以看到c2列并没有出现部分更新为1的情况,也就是说整表更新的这条操作回滚了。

细心点可以看到binlog pos号也没有发生变化

root@127.0.0.1 (helei)> show master status;+------------------+-----------+--------------+------------------+| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB |+------------------+-----------+--------------+------------------+| mysql-bin.000004 | 124886658 |              |                  |+------------------+-----------+--------------+------------------+1 row in set (0.00 sec)


Part4:诡异

前三章看完后,我们来看下有什么地方是诡异的,在生产环境中,由于不知道刚刚那条SQL是否已经更新了部分数据,我们采取了这种方式来验证。

root@127.0.0.1 (helei)> select * from helei3 where a='0';+------+------+| a    | b    |+------+------+| 0    | b    || 0    | c    |+------+------+2 rows in set (0.00 sec)root@127.0.0.1 (helei)> select * from helei3 where a=0;+------+------+| a    | b    |+------+------+| 0    | b    || 0    | c    || zz   | zz   |+------+------+3 rows in set (0.00 sec)

发现数据不一致,生产环境的更唬人一些,列中并没有存储0,而都是字母或纯数字,当我执行上述两个SQL的时候,发现结果差了非常多,还爆出了很多的warnings。

| Warning | 1292 | Truncated incorrect DOUBLE value: 'XXX' |

那么我想知道刚刚的误操作到底是不是生效了呢,为什么会出现差个引号结果就差这么多呢?



分析

Part1:构建数据

root@127.0.0.1 (helei)> insert into helei3 values('zz','zz');root@127.0.0.1 (helei)> select * from helei3;+------+------+| a    | b    |+------+------+| 1    | a    || 0    | b    || 0    | c    || zz   | zz   |+------+------+4 rows in set (0.00 sec)


Part2:查询对比

那么这时我们执行一条查询会有两种结果

root@127.0.0.1 (helei)> select * from helei3 where a='0';+------+------+| a    | b    |+------+------+| 0    | b    || 0    | c    |+------+------+2 rows in set (0.00 sec)root@127.0.0.1 (helei)> select * from helei3 where a=0;+------+------+| a    | b    |+------+------+| 0    | b    || 0    | c    || zz   | zz   |+------+------+3 rows in set (0.00 sec)


这是为什么呢?


Part3:root cause

root@127.0.0.1 (helei)> select 'zz'=0;+--------+| 'zz'=0 |+--------+|      1 |+--------+1 row in set, 1 warning (0.00 sec)root@127.0.0.1 (helei)> select 'zz3'=0;+---------+| 'zz3'=0 |+---------+|       1 |+---------+1 row in set, 1 warning (0.00 sec)root@127.0.0.1 (helei)> select '3'=0;+-------+| '3'=0 |+-------+|     0 |+-------+1 row in set (0.00 sec)


可以看出,当包含字母的时候,mysql认为=0是真,并抛出warning。

root@127.0.0.1 (helei)> show warnings;+---------+------+----------------------------------------+| Level   | Code | Message                                |+---------+------+----------------------------------------+| Warning | 1292 | Truncated incorrect DOUBLE value: 'zz' |+---------+------+----------------------------------------+1 row in set (0.00 sec)



Part4:MySQL Doc

In InnoDB, all user activity occurs inside a transaction. If autocommit mode is enabled, each SQL statement forms a single transaction on its own. By default, MySQL starts the session for each new connection with autocommit enabled, so MySQL does a commit after each SQL statement if that statement did not return an error. If a statement returns an error, the commit or rollback behavior depends on the error.


Part5:我的理解

InnoDB存储引擎符合事务的ACID特性。 它将一次完成所有操作,或者在中断时不会执行操作和回滚。 InnoDB也是MySQL 5.5及以上版本的默认引擎。

但是对于非事务性的MyISAM存储引擎。 他的原子操作是一行一行完成的。 所以如果你中断这个过程,那就会更新/删除到哪里就到哪里了。


--总结--

通过本文,您能了解到update中使用了and这种错误语法带来的严重后果,以及在SQL语句执行完之前,ctrl +c 到底有没有效果~由于笔者的水平有限,编写时间也很仓促,文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。



喜欢的读者可以点个赞来个关注,您的赞美和关注是对笔者继续发文的最大鼓励与支持!

更新 数据 诡异 结果 时候 条件 错误 人员 引擎 笔者 语句 语法 存储 危险 一行 事务 后果 地方 字母 情况 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 小学网络安全生产月活动方案 安阳软件开发简介 黄浦区软件开发技术服务价格 国电通网络技术有限公司 内存数据库 集群 计算机网络技术第九章教案 摄像头绑定在本地服务器 服务器的3u5u是什么意思 梦幻西游燕赵服务器怎么样 数据库表能用中文名吗 软件开发培训完找不到工作 中国知网是不是文摘型数据库 软件开发调用方式 视频管理服务器和硬盘录像机区别 服务器登入失败电脑打不开 软件开发大数据技术 我的世界好玩的服务器电脑版网易 thinkphp数据库配置文件 怎么给服务器配置centos dota2+数据库 网络安全包括哪些种类 手机软件开发如何 kld数据库是什么 海南佰翊互联网科技有限公司 网络安全工程师有年龄限制么 梦幻西游深夜服务器会掉线吗 第一代服务器叫什么服务器 科技互联网行业人士 和平精英的刺激战场服务器在哪 核心网络技术支撑考试
0