首页 > 开发 > MySQL > 正文

我用不小心用 mysql 的int(11) 存了 手机号,数据都有问题,有办法恢复么?

2017-09-08 09:11:20  来源:网友分享

我用不小心用 mysql 的int(11) 存了用户的手机号,结果里面存的数据都是 10 位的,而且也不是单纯的被截断了一位,比如手机号 18345231102 会被转成 4294967295有办法恢复么,急。。。。。

问题补充:1.数据库的存的手机号是类似这样的51112963343770955094722102415440968372770221786305239645098525174121477919941663290693306702852184282645423829764371811997122212897453969451493118167158788764318877374212501107794384847325325

2.我问了下运维,是开了binlog 的,然后我跟他们要了一份。把里面所有的用户填手机号的sql的都找了出来,但是神奇的是sql里的手机号跟数据库里的是一样的,难道binlog里的sql是溢出之后的?

解决方案

对不起LZ了,这个答案正像Sunyanzi指出的,MySQL不是把高位字节吃掉而是转成了Int的最大值。考虑到原先提交的答案还是花了点心思写的,就还留在这里了,也许对其他高位字节溢出的问题有所帮助。


这个有点意思,问题出在int只有4个字节,而手机号码是11位的十进制值由5个字节组成,所以转成int后最高位的第5个字节被“吃掉了”,然后就杯具了。

解决思路:把丢失的那个字节找回来。按照当前手机号码范围130 0000 0000到189 9999 9999经分析,丢失的高位字节可能是0x03或者0x04。因此加上0x03或者0x04恢复后的值(Long长整型)符合手机号码范围/格式,就可以得到原始值了。遗留问题: 有可能出现加0x03和0x04都符合手机号码范围/格式的情况,取加0x04的结果(没法子的事情)

好了,上代码(Java)代码:

/** * 按照当前手机号码范围130 0000 0000到189 9999 9999经分析,丢失的高位字节可能是0x03或者0x04。 * 因此加上0x03或者0x04恢复后的值(Long长整型)符合手机号码范围/格式,就可以得到原始值了。 * 有可能出现加0x03和0x04都符合手机号码范围/格式的情况,取加0x04的结果(没法子的事情) *  * @param original 溢出前的原始11位手机号码 * @return 转int之后,再重新恢复得到的11位手机号码 */public static long recover(long original) {    Pattern p = Pattern.compile("1[3,4,5,8]\\d{9}");    // 更精确的手机号段,但可能不是最新的,这里先不使用。参考: http://wenku.baidu.com/view/9d088df30242a8956bece435.html    // Pattern.compile("(133|153|180|181|189|134|135|136|137|138|139|150|151|152|157|158|159|182|183|187|188|130|131|132|155|156|185|186|145|147)\\d{8}");    int errorInt = (int) original;    System.out.println("溢出前的long值:" + original);    System.out.println("溢出后的int值:" + errorInt);    System.out.println("溢出前的16进制值:" + Long.toHexString(original));    String hexA = "000000000000" + Long.toHexString(errorInt);    hexA = hexA.substring(hexA.length() - 8);    System.out.println("溢出后的16进制值(左补0):" + Long.toHexString(errorInt));    String hex1 = "4" + hexA;    System.out.println("补全后的16进制值1:" + hex1);    BigInteger bi1 = new BigInteger(hex1, 16);    long rt1 = bi1.longValue();    System.out.println("补全后的Long值:" + rt1);    String hex2 = "3" + hexA;    System.out.println("补全后的16进制值2:" + hex2);    BigInteger bi2 = new BigInteger(hex2, 16);    long rt2 = bi2.longValue();    System.out.println("补全后的Long值2:" + rt2);    final boolean m1 = p.matcher(String.valueOf(rt1)).matches();    final boolean m2 = p.matcher(String.valueOf(rt2)).matches();    long rt = 0;    if (m1 && m2) {        // 加3加4都符合手机号码格式        System.err.println("加3加4都符合手机号码格式的溢出后int值:" + errorInt + ". 2个可能的恢复值为: " + rt1 + ", " + rt2);        //有可能出现加0x03和0x04都符合手机号码范围/格式的情况,取加0x04的结果(没法子的事情)        rt = rt1;    } else {        if (m1) {            rt = rt1;        }        if (m2) {            rt = rt2;        }    }    System.out.println("恢复后的符合手机号码格式的值:" + rt + "\n\n");    return rt;}