Bug #35551 Maria: crash in REPAIR TABLE/ENABLE KEYS if using repair-with-keycache method
Submitted: 25 Mar 2008 13:24 Modified: 24 Apr 2008 16:52
Reporter: Guilhem Bichot Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Maria storage engine Severity:S3 (Non-critical)
Version:5.1-maria OS:Any
Assigned to: Guilhem Bichot CPU Architecture:Any

[25 Mar 2008 13:24] Guilhem Bichot
Description:
mysqld: ma_pagecache.c:3184: pagecache_read: Assertion `block->type == PAGECACHE
_EMPTY_PAGE || block->type == type || type == PAGECACHE_LSN_PAGE || type == PAGE
CACHE_READ_UNKNOWN_PAGE || block->type == PAGECACHE_READ_UNKNOWN_PAGE' failed.
#5  0x085d1814 in pagecache_read (pagecache=0x8f4ebc0, file=0x8ffeb5c, 
    pageno=1, level=0, buff=0x8ff3a40 "X;ÿ\bp\001î·_", 
    type=PAGECACHE_PLAIN_PAGE, lock=PAGECACHE_LOCK_LEFT_UNLOCKED, 
    page_link=0xb6a4e3a0) at ma_pagecache.c:3180
#6  0x0860b060 in _ma_scan_block_record (info=0x8ffe8e8, 
    record=0x8fee868 "\020\002î·\020\002î· ", record_pos=0, 
    skip_deleted=1 '\001') at ma_blockrec.c:5061
#7  0x086322f8 in sort_get_next_record (sort_param=0xb6a4e768)
    at ma_check.c:4349
#8  0x0862bdd2 in maria_repair (param=0xb6a4f03c, info=0x8ffe8e8, 
    name=0xb6a4ed68 "./test/t1", rep_quick=1 '\001') at ma_check.c:2362
#9  0x085b2fcd in ha_maria::repair (this=0x8ff9d70, thd=0x8fb89b8, 
    param=@0xb6a4f03c, do_optimize=false) at ha_maria.cc:1340
#10 0x085b3cd2 in ha_maria::repair (this=0x8ff9d70, thd=0x8fb89b8, 
    check_opt=0x8fb9fe0) at ha_maria.cc:1176
#11 0x083a1918 in handler::ha_repair (this=0x8ff9d70, thd=0x8fb89b8, 
    check_opt=0x8fb9fe0) at handler.cc:2516
#12 0x083c3037 in mysql_admin_table (thd=0x8fb89b8, tables=0x8fee668, 

I originally saw this with a SPATIAL key during ALTER TABLE ENABLE KEYS(such index always force a repair-with-keycache, see maria_too_big_key_for_sort()), but REPAIR TABLE QUICK EXTENDED fires the assertion even with non-SPATIAL keys.

How to repeat:
Run this test (inspired from maria-gis-rtree.test):

CREATE TABLE t1 (
  line varchar(100) not null,
  kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po',
  name VARCHAR(32),
  KEY (line)
) engine=maria;

ALTER TABLE t1 DISABLE KEYS;

INSERT INTO t1 (name, kind, line) VALUES 
  ("Aadaouane", "pp", GeomFromText("POINT(32.816667 35.983333)")),
  ("Aadassiye", "pp", GeomFromText("POINT(35.816667 36.216667)")),
  ("Aadbel", "pp", GeomFromText("POINT(34.533333 36.100000)")),
  ("Aadchit", "pp", GeomFromText("POINT(33.347222 35.423611)")),
  ("Aadchite", "pp", GeomFromText("POINT(33.347222 35.423611)")),
  ("Aadchit el Qoussair", "pp", GeomFromText("POINT(33.283333 35.483333)")),
  ("Aaddaye", "pp", GeomFromText("POINT(36.716667 40.833333)")),
  ("'Aadeissa", "pp", GeomFromText("POINT(32.823889 35.698889)")),
  ("Aaderup", "pp", GeomFromText("POINT(55.216667 11.766667)")),
  ("Qalaat Aades", "pp", GeomFromText("POINT(33.503333 35.377500)")),
  ("A ad'ino", "pp", GeomFromText("POINT(54.812222 38.209167)")),
  ("Aadi Noia", "pp", GeomFromText("POINT(13.800000 39.833333)")),
  ("Aad La Macta", "pp", GeomFromText("POINT(35.779444 -0.129167)")),
  ("Aadland", "pp", GeomFromText("POINT(60.366667 5.483333)")),
  ("Aadliye", "pp", GeomFromText("POINT(33.366667 36.333333)")),
  ("Aadloun", "pp", GeomFromText("POINT(33.403889 35.273889)")),
  ("Aadma", "pp", GeomFromText("POINT(58.798333 22.663889)")),
  ("Aadma Asundus", "pp", GeomFromText("POINT(58.798333 22.663889)")),
  ("Aadmoun", "pp", GeomFromText("POINT(34.150000 35.650000)")),
  ("Aadneram", "pp", GeomFromText("POINT(59.016667 6.933333)")),
  ("Aadneskaar", "pp", GeomFromText("POINT(58.083333 6.983333)")),
  ("Aadorf", "pp", GeomFromText("POINT(47.483333 8.900000)")),
  ("Aadorp", "pp", GeomFromText("POINT(52.366667 6.633333)")),
  ("Aadouane", "pp", GeomFromText("POINT(32.816667 35.983333)")),
  ("Aadoui", "pp", GeomFromText("POINT(34.450000 35.983333)")),
  ("Aadouiye", "pp", GeomFromText("POINT(34.583333 36.183333)")),
  ("Aadouss", "pp", GeomFromText("POINT(33.512500 35.601389)")),
  ("Aadra", "pp", GeomFromText("POINT(33.616667 36.500000)")),
  ("Aadzi", "pp", GeomFromText("POINT(38.100000 64.850000)"));

repair table t1 quick extended;

Suggested fix:
What happens is:
REPAIR TABLE t1 QUICK EXTENDED first flushes all pages to disk, but keeping at least data pages in the cache (normal).
As this is a QUICK repair, sort_info->new_info==info and so in sort_get_next_record() we come to
        /*
          Scan on clean table.
          It requires a reliable data_file_length so we set it.
        */
        info->state->data_file_length= sort_info->filelength;
        flag= _ma_scan_block_record(info, sort_param->record,
                                    info->cur_row.nextpos, 1);
_ma_scan_block_record() reads data pages by using share->page_type (PLAIN at this moment, as ALTER TABLE ENABLE KEYS disables transactionality). But the page is found in the cache and it has type LSN, so the assertion fires.
Note that in sort_get_next_record() there is another branch which calls _ma_safe_scan_block_record() which looks half-safe: at one place it uses PAGECACHE_READ_UNKNOWN_PAGE but it also calls _ma_read_block_record2() which uses share->page_type so might exhibit the same bug.
[25 Mar 2008 13:35] Guilhem Bichot
This seems to work:
===== ../storage/maria/ma_check.c 1.84 vs edited =====
--- 1.84/storage/maria/ma_check.c       2008-03-08 01:06:57 +01:00
+++ edited/../storage/maria/ma_check.c  2008-03-25 14:29:05 +01:00
@@ -4332,7 +4332,8 @@ static int sort_get_next_record(MARIA_SO
     for (;;)
     {
       int flag;
-
+      enum pagecache_page_type save_page_type= share->page_type;
+      share->page_type= PAGECACHE_READ_UNKNOWN_PAGE;
       if (info != sort_info->new_info)
       {
         /* Safe scanning */
@@ -4349,6 +4350,7 @@ static int sort_get_next_record(MARIA_SO
         flag= _ma_scan_block_record(info, sort_param->record,
                                     info->cur_row.nextpos, 1);
       }
+      share->page_type= save_page_type;
       if (!flag)
       {
        if (sort_param->calc_checksum)
[24 Apr 2008 16:52] Guilhem Bichot
ChangeSet@1.2630.2.1, 2008-04-24 17:22:51+02:00, guilhem@gbichot4.local +30 -0
  WL#3072 - Maria Recovery
  Recovery of R-tree and fulltext indices.
  Fix for BUG#35551 "Maria: crash in REPAIR TABLE/ENABLE KEYS if using
  repair-with-keycache method".