解决mysql Found too long record(XX) at XX问题
最近我们主从的一个从库上报了一个主从不同步的错误,具体错误内容如下
Last_Error: Error 'Duplicate entry '66139-5-1160' for key 1' on query. Default database: 'test'. Query: 'insert into tbl_list (FLD_ID, FLD_TYPE, FLD_ITEM_ID) values (66139, 5, 1160)'
刚开始还以为是主键冲突,于是就去查询该表的数据
(root@localhost:16:26:25)[test]> select * from tbl_list;
ERROR 145 (HY000): Table './test/tbl_list' is marked as crashed and should be repaired
报表损坏,于是检查表
(root@localhost:16:26:26)[test]> check table tbl_list;
+---------------+-------+----------+---------------------------------+
| Table | Op | Msg_type | Msg_text |
+---------------+-------+----------+---------------------------------+
| test.tbl_list | check | error | Found too long record (23) at 0 |
| test.tbl_list | check | error | Corrupt |
+---------------+-------+----------+---------------------------------+
2 rows in set (0.00 sec)
报表长度超长,于是就修复表
(root@localhost:16:26:27)[test]>REPAIR table tbl_list;
+---------------+--------+----------+------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+---------------+--------+----------+------------------------------------------+
| test.tbl_list | repair | info | Wrong bytesec: 3- 0- 23 at 0; Skipped |
| test.tbl_list | repair | warning | Number of rows changed from 1 to 0 |
| test.tbl_list | repair | status | OK |
+---------------+--------+----------+------------------------------------------+
显示修复OK,重新检查表
(root@localhost:16:26:28)[test]>check table tbl_list;
+---------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------+-------+----------+----------+
| test.tbl_list | check | status | OK |
+---------------+-------+----------+----------+
于是执行将刚刚那句报错的语句重新执行一次
(root@localhost:16:26:29)[test]> insert into tbl_list (FLD_ID, FLD_TYPE, FLD_ITEM_ID) values (66139, 5, 1160);
Query OK, 1 row affected (0.00 sec)
从结果老看,数据已经进入数据库了,再检索数据
(root@localhost:16:26:25)[test]> select * from tbl_list;
ERROR 145 (HY000): Table './test/tbl_list' is marked as crashed and should be repaired
又损坏了,再经历检查修复,再查询的过程,发现表中的数据一条都没有。
(root@localhost:16:26:25)[test]>select * from tbl_list;
Empty set (0.00 sec)
看来有问题,于是上网去找,发现是mysql 本身的一个bug,从bug list查找,用户说的但表的类型为myisam的表,且建立表的时候指定了这两个参数很有可能发送row_format=dynamic和checksum=1,
再说说我们的环境吧
(root@localhost:16:52:39)[test]> show variables like "%version%";
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| protocol_version | 10 |
| version | 5.0.37-log |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | unknown-linux-gnu |
+-------------------------+---------------------+
表结构
(root@localhost:16:52:39)[test]> SHOW CREATE TABLE tbl_list;
CREATE TABLE `tbl_list` (
`FLD_ID` int(11) NOT NULL default '0',
`FLD_TYPE` int(11) NOT NULL default '0',
`FLD_ITEM_ID` int(11) NOT NULL default '0',
PRIMARY KEY (`FLD_ID`,`FLD_TYPE`,`FLD_ITEM_ID`)
)ENGINE=MyISAM DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;
按理来说,应该执行这样的一个语句没有什么问题,但在这个版本中,有这个bug存在,另外我把该出问题的数据在,5.1.47上重新执行上述过程,没有发生上述问题。没有办法不能换版本,只能想起他方法,于是重新建立表,去掉CHECKSUM=1选项,保留动态列的选项,毕竟动态列还是用得比较的多,况且不是一些十分重要的数据,丢了还可以重建出来,还是保留这个选项吧。就没有发生上面的问题了,不过我个人还是建议把表改成innodb的,不过研发方不改,我也没有办法,就这样先将就用用吧,再者别被mysql报错的表象迷惑了,要找出问题的根本。