mysql实际使用过程中碰到的一些有…

这一段时间帮客户维护sqlproxy的mysql集群过程中碰到了一些比较古怪又挺有意思的问题,记录一下:


1. 主从复制延迟大

主从复制延迟的问题一直都有,但用户现场是测试环境,网络没问题,应用的压力也很小,这种情况下基本上就是写的sql语句的问题了。
复制的模式的mixed,对于复制安全的语句使用statement复制,不安全的使用row复制。所以导致主从延迟大的可能性主要有2方面,一种是不安全的语句导致了非常大的row级binlog,从而导致了非常大的网络传输和执行时间;另一种是语句的执行在slave的效率底下,远慢于master上的执行;
对于该问题具体的描述与解决可以在我之前的blog: http://blog.sina.com.cn/s/blog_4673e60301015dyn.html
中找到。
概括来说就是有一条复制不安全的修改语句操作了一张没有主键的表,导致了row复制。而row级的binlog在slave上执行的时候需要定位需要修改的行,这个过程中由于没有主键,mysql5.5执行了N*M的笛卡尔乘集的匹配,导致了巨大的执行时间与延迟。 这个问题在即将GA的mysql5.6中得到了解决,不同与5.5的N*M,5.6通过新的hash定位算法只需要N+M的代价。具体的可以看: http://binlogtorelaylog.blogspot.com/2012/08/Batch-operations-in-RBR.html

2. 业务在运行过程中莫名的数据丢失
客户程序会定时向一张表进行数据插入,每条插入的数据都会有一个字段记录now()的时间。同时后台另一个线程会定时地从该表中采集数据进行统计分析,然后把分析过的数据删除:
begin;
select ... where time>T1 and time< T2;
[间隔一段时间]
delete ... where time>T1 and time
commit;

首先想到的是innodb隔离级别,因为innodb的读多版本,而写操作始终操作的是最新的数据。所以这个时间间隔中可能有新的满足time>T1 and time
然而用户说他们条件中的T1和T2是当前时间前1s,认为应该可以避免这个情况。
其实避免不了,因为时间字段的值是来自now()函数,该函数的值是该语句到达server的时间(真正执行前),而该语句真正被插入并且可以被其他事务看到的时间要晚于这个时间,而且这个时间间隔是不确定的,所以提前1s是无法避免之前说到的情况的。
给出的建议的解决方案如下:

修改源表添加一列 is_select INT default 0,然后先按照条件进行修改(把
对应行的is_select字段设为1). 然后select的条件修改为 where is_select=1,
删除的条件也修改为where is_select=1; sql语句模式为:
update ... set is_select=1 where time>T1 and time< T2;
select ... where time>T1 and time< T2 and is_select=1;
delete ... where time>T1 and time< T2 and is_select=1;

需要注意的是不要给is_select 字段上索引。用户自己给这个字段上了索引,并且还使用事务,结果导致了大量的死锁的发生。 即便从正确使用索引的角度来说也不应给is_select上索引,因为该字段只有2种值,并且还经常被修改。

转载请注明出自高孝鑫的博客
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值