This patch for bug #32705 myisam corruption: Key in wrong position at
page 1024 with ucs2_bin
diff -Nur storage/myisam/mi_open.c.orig storage/myisam/mi_open.c
--- storage/myisam/mi_open.c.orig 2007-12-03 17:20:32.000000000 +0800
+++ storage/myisam/mi_open.c 2007-12-03 17:31:23.000000000 +0800
@@ -813,7 +813,7 @@
if (keyinfo->seg[0].flag & HA_PACK_KEY)
{ /* Prefix compression */
if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
- (keyinfo->seg->flag & HA_NULL_PART))
+ (keyinfo->seg->flag & HA_NULL_PART) ||
my_binary_compare(keyinfo->seg->charset))
keyinfo->bin_search=_mi_seq_search;
else
keyinfo->bin_search=_mi_prefix_search;
The diffrent methods used between creating keys and checking keys is the
reason to cause this error.
... ...
(1) mysql> insert into t values ('marshall\'s');
... ...
|-- _mi_ck_real_write_btree
|-- w_search
|-- _mi_prefix_search ( *keyinfo->bin_search)
... ...
(2) mysql> check table t extend;
... ...
|-- chk_index
|-- ha_key_cmp
|-- mi_compare_text
|-- my_strnncollsp_ucs2_bin
In ucs2, every character is represented by a two-byte Unicode code. The
function "_mi_prefix_search" is not suitable for this kind of character set.
If we use charaset "ucs2" and collation "ucs2_bin" for a key, we should
use this comparing function "my_strnncollsp_ucs2_bin" to order the
key's position during the period of inserting records to table. When
executing the "check table t extended" statement, the key will be
checked by using this function too.
So I think we should add a condition like
"my_binary_compare(keyinfo->seg->charset)" or
"(keyinfo->seg->charset->number == 90)". Because the function pointer
"keyinfo->bin_search" should point to "_mi_seq_search" when setting up
key functions.
The flow of function "_mi_seq_search" as following:
_mi_seq_search
|-- ha_key_cmp
|-- mi_compare_text
|-- my_strnncollsp_ucs2_bin
Test and result:
mysql> create table t1 (c1 char(255) character set ucs2 collate ucs2_bin
not null,key(c1))
-> engine=myisam;
Query OK, 0 rows affected (0.17 sec)
mysql> insert into t1 values ('marshall\'s');
Query OK, 1 row affected (0.13 sec)
mysql> insert into t1 values ('marsh');
Query OK, 1 row affected (0.07 sec)
mysql> check table t1 extended;
+---------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+-------+----------+----------+
| test.t1 | check | status | OK |
+---------+-------+----------+----------+
1 row in set (0.00 sec)
mysql> select * from t1 order by c1;
+------------+
| c1 |
+------------+
| marsh |
| marshall's |
+------------+
2 rows in set (0.10 sec)
mysql> select * from t1 order by c1 desc;
+------------+
| c1 |
+------------+
| marshall's |
| marsh |
+------------+
2 rows in set (0.00 sec)
| Thread |
|---|
| • Patch for bug #32705 | Lu Jingdong | 3 Dec |