Bug #12243 MySQL Server crashes with 2 cursors (+ commit)
Submitted: 28 Jul 2005 18:04 Modified: 10 Aug 2005 16:40
Reporter: Andrey Hristov Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S1 (Critical)
Version:5.0.10-beta-200507260 OS:Linux (SLES9)
Assigned to: Konstantin Osipov CPU Architecture:Any

[28 Jul 2005 18:04] Andrey Hristov
Description:
With the attached program the server crashes with SIGSEGV :
(gdb) bt
#0  0x0000000000768aa4 in read_view_sees_trx_id (view=0x0, trx_id={high = 0, low = 1666771}) at read0read.ic:53
#1  0x0000000000762def in lock_clust_rec_cons_read_sees (rec=0x2a97bc27ce "TAPOPAEINSW%RTW_RT0019", index=0x2a970b44b8, offsets=0x4114dad0, view=0x0)
    at lock0lock.c:522
#2  0x00000000006fa52a in row_search_for_mysql (buf=0x372ff68 "`\006TAPOPA    \020EINSW%RTW_RT0018", ' ' <repeats 95 times>, "\200 ", mode=2,
    prebuilt=0x2a971c4cb8, match_mode=1, direction=1) at row0sel.c:3752
#3  0x000000000064f5e5 in ha_innobase::general_fetch (this=0x377bb08,
    buf=0x372ff68 "`\006TAPOPA    \020EINSW%RTW_RT0018", ' ' <repeats 95 times>, "\200 ", direction=1, match_mode=1) at ha_innodb.cc:3970
#4  0x000000000064f71b in ha_innobase::index_next_same (this=0x377bb08,
    buf=0x372ff68 "`\006TAPOPA    \020EINSW%RTW_RT0018", ' ' <repeats 95 times>, "\200 ", key=0x379e460 "\006", keylen=12) at ha_innodb.cc:4026
#5  0x00000000005d06bc in join_read_next_same (info=0x379e2c0) at sql_select.cc:9913
#6  0x00000000005cf46c in sub_select (join=0x379c748, join_tab=0x379e248, end_of_records=false) at sql_select.cc:9375
#7  0x00000000005bbc53 in Cursor::fetch (this=0x37a3da8, num_rows=1) at sql_select.cc:1864
#8  0x00000000005e8217 in mysql_stmt_fetch (thd=0x37905c0, packet=0x3726fe1 "\002", packet_length=9) at sql_prepare.cc:2247
#9  0x000000000057aed2 in dispatch_command (command=COM_STMT_FETCH, thd=0x37905c0, packet=0x3726fe1 "\002", packet_length=9) at sql_parse.cc:1634
#10 0x000000000057a8ad in do_command (thd=0x37905c0) at sql_parse.cc:1467
#11 0x0000000000579a67 in handle_one_connection (arg=0x3760e30) at sql_parse.cc:1116
#12 0x0000002a95992919 in start_thread () from /lib64/tls/libpthread.so.0
#13 0x0000002a95eff8a3 in thread_start () from /lib64/tls/libc.so.6

How to repeat:
Use the attached program.
[28 Jul 2005 18:06] Andrey Hristov
bug12243

Attachment: bug12243.c (text/x-csrc), 5.43 KiB.

[28 Jul 2005 18:47] Jorge del Conde
Hi Andrey,

I was able to reproduce this bug using a recent 5.0 pull.
[28 Jul 2005 22:44] Andrey Hristov
the table with the data

Attachment: dump.sql (application/octet-stream, text), 32.13 KiB.

[29 Jul 2005 7:51] Andrey Hristov
Ultra simplified test case. Table definition in the source.

Attachment: bug12243_2.c (text/x-csrc), 1.20 KiB.

[29 Jul 2005 8:10] Jan Lindström
Based on stack trace server crashes in row_search_for_mysql because no read view is assigned. This could be because MySQL does not call innobase_set_cursor_view() after commit in the next fetch on other cursor. I think this bug is in MySQL server code not inside of InnoDB code.  Thus, every time MySQL does a operation on cursor it is needed first to set what cursor should be used. MySQL may not assume that InnoDB has correct read view for cursor assigned. Actually, after InnDB returns from row_search_for_mysql cursor read view is detached from the transaction to make sure that when row_search_for_mysql is called next time you must set cursor read view to correct cursor before you may fetch from it.
[29 Jul 2005 11:07] Jan Lindström
Confirmed that this bug is because cursor view was not set before fetch. Bug is in MySQL server code.

#0  0x0833e9ba in read_view_sees_trx_id (view=0x0, trx_id=
      {high = 0, low = 33025}) at read0read.ic:53
#1  0x0836167f in lock_clust_rec_cons_read_sees (rec=0x40df409b "",
    index=0x40add568, offsets=0x637a7b8c, view=0x0) at lock0lock.c:522
#2  0x08313c61 in row_search_for_mysql (buf=0x8c71880 "￿\001", mode=1,
    prebuilt=0x40ade668, match_mode=0, direction=1) at row0sel.c:3759
#3  0x0827301b in ha_innobase::general_fetch(char*, unsigned, unsigned) (
    this=0x8c71758, buf=0x8c71880 "￿\001", direction=1, match_mode=0)
    at ha_innodb.cc:3970
#4  0x08273409 in ha_innobase::rnd_next(char*) (this=0x8c71758,
    buf=0x8c71880 "￿\001") at ha_innodb.cc:4161
#5  0x0825d148 in rr_sequential (info=0x8c6a1ac) at records.cc:193
#6  0x081f6a5f in sub_select (join=0x8c69128, join_tab=0x8c6a170,
    end_of_records=false) at sql_select.cc:9374
#7  0x081e5198 in Cursor::fetch(unsigned long) (this=0x8c6d3e0, num_rows=1)
    at sql_select.cc:1864
#8  0x0820f146 in mysql_stmt_fetch(THD*, char*, unsigned) (thd=0x8c362b0,
    packet=0x8c58ff9 "\002", packet_length=9) at sql_prepare.cc:2242
#9  0x081a5d8b in dispatch_command(enum_server_command, THD*, char*, unsigned)
    (command=COM_STMT_FETCH, thd=0x8c362b0, packet=0x8c58ff9 "\002",
    packet_length=9) at sql_parse.cc:1634
#10 0x081a56e3 in do_command(THD*) (thd=0x8c362b0) at sql_parse.cc:1467
#11 0x081a47fc in handle_one_connection (arg=0x8c362b0) at sql_parse.cc:1116
[6 Aug 2005 7:20] Konstantin Osipov
I tracked the bug down. 
The bug is that InnoDB does not register it's handlerton in the list of statement handlertons
when opening the second cursor.
In sql_select.cc we have the following code to create a cursor read view:
  for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++)
  {
    const handlerton *ht= *pht;
    close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
    if (ht->create_cursor_read_view)
    {
      info->ht= ht;
      info->read_view= (ht->create_cursor_read_view)();
      ++info;
    }
  }

So, to create a read view the storage engine handlerton must be registered in
the list of handlertons used in the statement.

But in ha_innobase::external_lock trans_register_ha is called only if trx->n_mysql_tables_in_use is zero:

              } else if (trx->n_mysql_tables_in_use == 0) {
                        innobase_register_stmt(thd);
                }

if we have an open active cursor within the transaction, this count is not reset, and is not
null.
So, InnoDB doesn't register the handlerton for subsequent cursors.
I will try to write a patch shortly. Jan: please review.
[10 Aug 2005 14:56] Konstantin Osipov
Subject: bk commit - 5.0 tree (konstantin:1.1975) BUG#11832                     

ChangeSet
  1.1975 05/08/10 18:36:13 konstantin@mysql.com +5 -0
  A fix and a test case for Bug#12243 "MySQL Server crashes with 2
  cursors (+ commit)" and Bug#11832 "Server crash with InnoDB + Cursors"
  See comments to the changed files.
[10 Aug 2005 14:59] Konstantin Osipov
Approved by Heikki Tuuri via email.

http://lists.mysql.com/internals/28111
[10 Aug 2005 15:00] Konstantin Osipov
Fixed in 5.0, currently tagged 5.0.12
[10 Aug 2005 16:40] Jon Stephens
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

Documented in 5.0.12 changelog.