由 "select *" 引发的“惨案”
今天凌晨做发布, 要合并多个分数据库的表数据到主数据库中, 有 30+ 分数据库。 前面都比较顺利, 在临近结束时,突然发现一个字段的值插入错误。 有一个表 T,字段分别为 (f1, f2, f3, gmt_create, gmt_modify, name) 。 假设分数据库为 a1, a2, ..., a30 , 主数据库为 A 。 合并的逻辑是: 从 a1, a2, ..., a30 取出对应的字段, 依次插入到 主数据库中。
aRet = adb.query("select * from T")
allTuples = []
for (f1, f2, f3, gmt_create , gmt_modify, name) in aRet:
allTuples.append((f1, f2, f3, gmt_create, gmt_modify, name))
Adb.executeMany("insert into T(f1, f2, f3, gmt_create, gmt_modify, name) values(%s, %s, %s, %s, %s, %s)", allTuples)
log.info(allTuples)
Adb.commit()
NOTE: 这里会将 allTuples 分成 1000 个元组一片进行提交执行。 不过不影响此处的理解。
那么, 这会有什么问题呢? 初看上去似乎没什么, 但是“惨案” 就这样发生了。
有一个集群 ai 的表 T 的字段顺序跟其他集群的略有不同。其表字段顺序是 (f1, f2, f3, name , gmt_create, gmt_modify) 。 这样从 ai 取出的数据 (f1, f2, f3, name, gmt_create, gmt_modify) 将插入到 A 的 (f1, f2, f3, gmt_create, gmt_modify, name) , 也就是说, a1.name 插入到 A.gmt_create, a1.gmt_create 插入到 A.gmt_modify, a1.gmt_modify 插入了 A.name , 由于 gmt_create , gmt_modify, name 均为字符串, 因此没有报错。 验证的时候, 由于另外一个地方因其他原因报了大量错误,掩盖了这个问题。
解决的办法很简单: 将 "select * from T" 改为 "select f1, f2, f3, gmt_create , gmt_modify, name from T"
教训: 在做“逐字段取出-插入” 的数据库操作时, 切忌使用 “select * ”
发现数据插入错误之后, 马上进行清空和重新执行。 这时, 更糟糕的事情发生了。 由于清空操作要考虑将对 T.A 的新改动(考虑到发布过程中会有外部调用修改T.A的数据)同步到 T.ai 。 而上述已经对 T.A 进行了大量改动, 因此会以 T.A 的数据为准, 对 T.ai 的相应记录进行回写, 结果将 ai 的原数据覆盖了, 且没有预先做表备份。 ai 的数据就这样丢失了!
教训: 合并过程中, 最好不要回写源数据库, 降低复杂性; 如果一定要回写源数据库, 要单独做一个脚本, 取名更明显, 且要做表备份操作。
现在必须马上恢复数据! 当时差点忘了, 由于 db.executeMany 接口没办法获取到直接执行的SQL, 因此昨天早上思虑再三,新添了一行代码使用了 log.info(allTuples) , 记录下了所要插入的源数据。 万一出问题, 避免从 DB 中取执行SQL的麻烦。 不过, 由于偷了一点懒, 打印出的 allTuples 的格式相当难以解析, 费了不少劲才将 <primarykey, name> 的关系取出来, 重新做了订正。 昨天早上的那行代码成了今天早上的救命稻草之一。
教训: 对数据库的insert, update, delete 操作一定要加日志。 如果数据库接口不方便直接打印SQL的日志, 就要单独打印出源数据以备后用。 此外, 最好不要偷懒, 因为每一点偷懒都会对后面某个时候造成障碍, 而稍微做的便利一点, 就会对后续产生有益的用处。 这都是活生生的教训。
由 "select *" 引发的“惨案”的更多相关文章
- try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案
如题,ajax请求报错:try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案 要么是404,要么是40 ...
- 记一次真实的线上事故:一个update引发的惨案!
目录 前言 项目背景介绍 要命的update 结语 前言 从事互联网开发这几年,参与了许多项目的架构分析,数据库设计,改过的bug不计其数,写过的sql数以万计,从未出现重大纰漏,但常在河边走,哪 ...
- 视图合并、hash join连接列数据分布不均匀引发的惨案
表大小 SQL> select count(*) from agent.TB_AGENT_INFO; COUNT(*) ---------- 1751 SQL> select count( ...
- 一个purge参数引发的惨案——从线上hbase数据被删事故说起
在写这篇blog前,我的心情久久不能平静,虽然明白运维工作如履薄冰,但没有料到这么一个细小的疏漏会带来如此严重的灾难.这是一起其他公司误用puppet参数引发的事故,而且这个参数我也曾被“坑过”. ...
- 一次dns缓存引发的惨案
时间2015年的某个周六凌晨5点,公司官方的QQ群有用户反馈官网打不开了,但有的用户反馈可以打开,客服爬起来自己用电脑试了一下没有问题,就给客户反馈说,可能是自己网络的问题,请过会在试试.早点8点,越 ...
- 由select引发的思考
一.前言 网络编程里一个经典的问题,selec,poll和epoll的区别?这个问题刚学习编程时就接触了,当时看了材料很不明白,许多概念和思想没有体会,现在在这个阶段,再重新回头看这个问题,有一种豁然 ...
- ogg:Extract 进程遇长事务执行 Forcestop 引发的惨案
http://www.linuxidc.com/Linux/2015-04/115777.htm SQL> select t.addr,t.START_DATE from v$transacti ...
- kafka的maxPollIntervalMs设置太小引发的惨案 (转)
本地启动kafka后,不断报一下信息: 表示本地consumer节点在不断的重新加入group,并且不断伴随着offset commit失败. 具体原因是因为ConsumerCoordinator没有 ...
- MySQL left join 引发的惨案
当我用这个进行更改值时,type未控制order表 其他数据被更改 还好备份数据表了(这里就体现了备份的重要性) UPDATE expense_order as a left join ( SELEC ...
随机推荐
- debian linux 下安装 netbeans(php)
1.安装netbians依赖jdk7 ,所以第一步是 apt-get install openjdk-7-jre 2.安装netbians 通过wget http://dlc.sun.com.edg ...
- ar1020 驱动移植 无效
移植ar1020的spi驱动.驱动移植过来后,在原来的板子上都能够正常运行,而在新的板子却没有效果. 最后查看新旧板子的AR1020的电路,发现M2引脚连接不同.M2高电平连接的touch是5线的接口 ...
- sql语句操作集锦
SQL操作全集 下列语句部分是Mssql语句,不可以在access中使用. SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT ...
- 30天,O2O速成攻略【8.29杭州站】
活动概况 时间:2015年8月29日13:30-16:30 地点:123茶楼(杭州上城区青年路27号2楼) 主办:APICloud.UPYUN.一起火 网址:www.apicloud.com 费用:免 ...
- 密码有效性验证失败。该密码不够复杂,不符合 Windows 策略要求
我在sqlserver2005中建立一个用户的时候,我的用户名和密码是一样的,它不允许我建立报“密码有效性验证失败.该密码不够复杂,不符合 Windows 策略要求”错误,我把密码改成其他一些就可以, ...
- RouteOS软路由HotSpot热点认证网关
实现要求: 实现局域网有线无线需在网页输入用户名和密码登录,不同用户登录有不同的访问内外网权限. 环境要求: 一台PC机安装三张网卡,第一张网卡连接外网,第二张网卡配置局域网,第三张网卡做配置连接使用 ...
- OpenGIS Simple feature access
OGIS规范定义的几何对象定义 Curve:A Curve is a 1-dimensional geometric object usually stored as a sequence of Po ...
- C# 6.0的新变化
自动属性初始化 (Initializers for auto-properties) 以前我们是这么写的 为一个默认值加一个后台字段是不是很不爽,现在我们可以这样写 只读属性的初始化(Getter-o ...
- 当数据库某张表数据发生变化时,更新c#程序中缓存的用法
参考:http://www.webkaka.com/tutorial/asp.net/2012/111912/(SqlDependency和SqlCacheDependency缓存的用法及具体步骤) ...
- Fusioncharts使用说明
背景 最近由于工作需要,再次接触到了Fusioncharts,但也有不足之处,现在官网上似乎是不支持flash的版本了,只能看到html5相关的javascript版本,无奈再次从网上搜索到了一些别人 ...