开发说查询一张表老是丢数据,sql是这样的:select * from CLICK where id >= xxx and id < xxx;
id是主键,自增字段。
经常丢失最大id附近的一些数据。
写个sql复现这种情况,select id from CLICK where id >= (select max(id)-100 from CLICK)
and id < (select max(id) from CLICK);
正常情况应该是会查到100条记录。但循环执行这个sql发现有时只能查到99条。找到那个丢失的id,select * from CLICK where
id=“丢失的id”;发现数据是正常的。
怀疑是不是表损坏了,check table后是正常的。
到底什么原因呢?
打开binlog看数据插入的情况,发现max(id)先于max(id)-1插入了,这是什么情况?仔细看binlog,原来这两个数据插入不是一个线程执行的。
这样大概能猜测到原因了:
线程1从计数器获得自增的max(id)(这儿假设是99),去插入数据。之后线程2从计数器获得max(id)(这儿应该是100),去像同一个表插入数据。
线程2的速度比线程1快,所以线程2先插入了id=100的数据,线程1还没有执行完。
这时去查询:select id from CLICK where id >= (select max(id)-100 from CLICK) and id
< (select max(id) from CLICK);
就会发现少了id=99的那条记录。
简单表示一下:
找到原因,那个开发的问题就很好解决了:select * from CLICK where id >= xxx and id < (select
max(id)-100 from CLICK);
其实线程间的速度差距是很微小的,应该在微妙或者毫秒级别,一般是感觉不到这种差距的。