MySQL遇到的一个卡库问题及对update的学习
2013-08-14 14:36
369 查看
近日遇到个卡库的问题,环境是MySQL5.5.12,报错信息如下
从报错信息上可以很直观的了解到,在主库上这个SQL部分被执行,并中断了。如果目前主库的数据是正确的,mysql建议在从库上skip这条SQL。
处理这个卡库比较简单,只要对比一下主库和从库的数据,然后稍作判断即可,我们也很快就skip过这个sql既恢复了服务。
但是处理完这个故障之后,忽然打算对update进行一下扩展的学习。
在这个场景下,开发的意图是用B的一个结果集更新A表的结果集,条件为A的一个字段等于B的一个字段。
但是明显,上面报错的SQL并不能实现这个需求,它会将A表的被更新字段全都刷成一个values,根本达不达业务的需求。那么这个SQL应该如何正确书写呢?
我们以2个表为例,aaa和bbb,表结构如下:
目前的需求就是将bbb表的y字段的值按照aaa.x=bbb.x的条件赋值给aaa的y字段。
首先,如果是打算每次更新一行,那么sql应该写成如下,然后使用脚本等外部手段循环所有的x值。(比如for i in循环等脚本)
然后,如果不打算使用外部脚本直接在mysql中实现呢? 那么可以按照如下写法:
因为x in (select x from bbb)被等效修改为 select x from aaa where exists (select 1 from bbb where aaa.x = bbb.x)
ps:这要感谢explain extended,可以使用show warnings查看sql被改写成什么。
具体可以参看:http://www.mysqlperformanceblog.com/2006/07/24/extended-explain/
最后,我们发现如果这么写也能实现我们的目的。
但是这是有前提的,第一bbb表的x字段需要唯一,并且比aaa表的x字段的values多,否则就会变成如下这种情况。有一列会被更新成null。
从结果看,应该是先进行了left join然后将aaa表的y列更新了,但是具体内部逻辑,没有找到相关官方文档支持,比较可惜,继续去找原因。
[ERROR] Slave SQL: Query partially completed on the master (error on master: 1317) and was aborted. There is a chan ce that your master is inconsistent at this point. If you are sure that your master is ok, run this query manually on the slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; . Query: 'update nls_quotes_delay_tmp A set t_volume =(select B.t_volume from nls_quotes_delay B where A.symbol=B.symbol and A.symbol='sina')', Error_code: 1317
从报错信息上可以很直观的了解到,在主库上这个SQL部分被执行,并中断了。如果目前主库的数据是正确的,mysql建议在从库上skip这条SQL。
处理这个卡库比较简单,只要对比一下主库和从库的数据,然后稍作判断即可,我们也很快就skip过这个sql既恢复了服务。
但是处理完这个故障之后,忽然打算对update进行一下扩展的学习。
在这个场景下,开发的意图是用B的一个结果集更新A表的结果集,条件为A的一个字段等于B的一个字段。
但是明显,上面报错的SQL并不能实现这个需求,它会将A表的被更新字段全都刷成一个values,根本达不达业务的需求。那么这个SQL应该如何正确书写呢?
我们以2个表为例,aaa和bbb,表结构如下:
aaa表: +------+------+ | x | y | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +------+------+ bbb表: +------+------+ | x | y | +------+------+ | 1 | 3 | | 2 | 4 | | 3 | 5 | +------+------+
目前的需求就是将bbb表的y字段的值按照aaa.x=bbb.x的条件赋值给aaa的y字段。
首先,如果是打算每次更新一行,那么sql应该写成如下,然后使用脚本等外部手段循环所有的x值。(比如for i in循环等脚本)
update aaa set y=(select y from bbb where bbb.x=2) where x=2;
然后,如果不打算使用外部脚本直接在mysql中实现呢? 那么可以按照如下写法:
update aaa set y=(select y from bbb where aaa.x=bbb.x) where x in (select x from bbb);
因为x in (select x from bbb)被等效修改为 select x from aaa where exists (select 1 from bbb where aaa.x = bbb.x)
> explain extended select * from aaa,bbb where aaa.x in (select x from bbb); +----+--------------------+-------+------+---------------+------+---------+------+------+----------+-------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+--------------------+-------+------+---------------+------+---------+------+------+----------+-------------------+ | 1 | PRIMARY | aaa | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where | | 1 | PRIMARY | bbb | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using join buffer | | 2 | DEPENDENT SUBQUERY | bbb | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where | +----+--------------------+-------+------+---------------+------+---------+------+------+----------+-------------------+ 3 rows in set, 1 warning (0.00 sec) > show warnings; +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1003 | select `test`.`aaa`.`x` AS `x`,`test`.`aaa`.`y` AS `y`,`test`.`bbb`.`x` AS `x`,`test`.`bbb`.`y` AS `y` from `test`.`aaa` join `test`.`bbb` where <in_optimizer>(`test`.`aaa`.`x`,<exists>(select 1 from `test`.`bbb` where (<cache>(`test`.`aaa`.`x`) = `test`.`bbb`.`x`))) | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
ps:这要感谢explain extended,可以使用show warnings查看sql被改写成什么。
具体可以参看:http://www.mysqlperformanceblog.com/2006/07/24/extended-explain/
最后,我们发现如果这么写也能实现我们的目的。
update aaa set y=(select y from bbb where aaa.x=bbb.x);
但是这是有前提的,第一bbb表的x字段需要唯一,并且比aaa表的x字段的values多,否则就会变成如下这种情况。有一列会被更新成null。
> select * from aaa; +------+------+ | x | y | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | | 4 | 4 | +------+------+ 4 rows in set (0.00 sec) > select * from bbb; +------+------+ | x | y | +------+------+ | 1 | 5 | | 2 | 6 | | 3 | 7 | +------+------+ 3 rows in set (0.00 sec) m7798:10.73.11.210 > update aaa set y=(select y from bbb where aaa.x=bbb.x); Query OK, 4 rows affected (0.01 sec) Rows matched: 4 Changed: 4 Warnings: 0 > select * from aaa; +------+------+ | x | y | +------+------+ | 1 | 5 | | 2 | 6 | | 3 | 7 | | 4 | NULL | +------+------+ 4 rows in set (0.01 sec)
从结果看,应该是先进行了left join然后将aaa表的y列更新了,但是具体内部逻辑,没有找到相关官方文档支持,比较可惜,继续去找原因。
相关文章推荐
- MySQL使用中遇到的一个问题
- 记录今天学习SQL遇到的一个小问题
- .net 使用mysql 遇到的一个问题
- 使用CocoaPods遇到一个问题:The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update ....
- MySQL与SqlServer中update操作同一个表问题
- MySQL学习2_CentOS下安装MySQL遇到问题:Access denied for user 'root'@'localhost'
- 遇到了一个关于for update用索引锁行的问题,悬而未解
- 在学习泛型中遇到的多态的一个小问题
- 在学习autotools遇到一个问题:make没有按照VPATH给的目录进行搜索,请大家指导一下。
- 触发器UPDATE遇到一个问题
- Stream学习过程中遇到的一个问题记录
- R语言连接MySQL遇到的一个问题:ERROR: configuration failed for package 'RMySQL'
- mysql更换主键遇到的一个问题
- 学习Mysql遇到的问题以及解决方法
- MySQL入门学习时,所遇到的问题(1)
- mysql中的一个特殊问题:You can’t specify target table ‘abc’ for update in FROM clause
- 遇到的一个mysql备份恢复的问题
- mysql学习笔记(二)之一个粗心的问题
- mysql中"ON DUPLICATE KEY UPDATE"语法遇到的问题
- C语言学习中连用两个scanf遇到的一个问题