Skip to content

Commit e7a265b

Browse files
author
aditya
committed
Bug#20391552 CRASH DURING MEMCACHE WORKLOAD
PROBLEM Cursor transaction (crsr_trx) is initially used for a read operation (get) , so the crsr_trx->read_only option is set as 1,and then the same transaction is used for write (set) operation without resetting the crsr_trx->read_only = 0 ,so it crashes in the innodb layer. Usually the background thread commits the transaction and resets it,but in this case the connection got the connection lock first and reused the transaction which leads to crash. FIX Check the status of crsr_trx->read_only before using the transaction for write.If set commit the transaction before reusing.
1 parent 230fc46 commit e7a265b

6 files changed

Lines changed: 53 additions & 4 deletions

File tree

plugin/innodb_memcached/innodb_memcache/include/innodb_cb_api.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/***********************************************************************
22
3-
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3+
Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
44
55
This program is free software; you can redistribute it and/or modify it
66
under the terms of the GNU General Public License as published by the
@@ -463,6 +463,13 @@ ib_err_t
463463
/*====================*/
464464
ib_crsr_t ib_crsr);
465465

466+
typedef
467+
ib_u32_t
468+
(*cb_trx_read_only_t)(
469+
/*==================*/
470+
ib_trx_t ib_trx);
471+
472+
466473
cb_open_table_t ib_cb_open_table;
467474
cb_read_row_t ib_cb_read_row;
468475
cb_insert_row_t ib_cb_insert_row;
@@ -524,5 +531,6 @@ cb_cursor_clear_trx_t ib_cb_cursor_clear_trx;
524531
cb_trx_get_start_time ib_cb_trx_get_start_time;
525532
cb_bk_commit_interval ib_cb_cfg_bk_commit_interval;
526533
cb_cursor_stmt_begin ib_cb_cursor_stmt_begin;
534+
cb_trx_read_only_t ib_cb_trx_read_only;
527535

528536
#endif /* innodb_cb_api_h */

plugin/innodb_memcached/innodb_memcache/src/innodb_api.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ static ib_cb_t* innodb_memcached_api[] = {
101101
(ib_cb_t*) &ib_cb_get_idx_field_name,
102102
(ib_cb_t*) &ib_cb_trx_get_start_time,
103103
(ib_cb_t*) &ib_cb_cfg_bk_commit_interval,
104-
(ib_cb_t*) &ib_cb_cursor_stmt_begin
104+
(ib_cb_t*) &ib_cb_cursor_stmt_begin,
105+
(ib_cb_t*) &ib_cb_trx_read_only
105106
};
106107

107108
/** Set expiration time. If the exp sent by client is larger than

plugin/innodb_memcached/innodb_memcache/src/innodb_engine.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,11 @@ innodb_conn_init(
810810
} else {
811811
/* Write cursor transaction exists.
812812
Reuse this transaction.*/
813+
if (ib_cb_trx_read_only(conn_data->crsr_trx)) {
814+
innodb_cb_trx_commit(
815+
conn_data->crsr_trx);
816+
}
817+
813818
assert(ib_cb_trx_start(conn_data->crsr_trx,
814819
engine->trx_level,
815820
true, false, NULL));
@@ -850,6 +855,11 @@ innodb_conn_init(
850855
engine->trx_level, true, false);
851856
trx_updated = true;
852857
} else {
858+
if (ib_cb_trx_read_only(conn_data->crsr_trx)) {
859+
innodb_cb_trx_commit(
860+
conn_data->crsr_trx);
861+
}
862+
853863
ib_cb_trx_start(conn_data->crsr_trx,
854864
engine->trx_level,
855865
true, false, NULL);
@@ -915,6 +925,12 @@ innodb_conn_init(
915925
engine, idx_crsr, lock_mode);
916926
}
917927
} else {
928+
929+
if (ib_cb_trx_read_only(conn_data->crsr_trx)) {
930+
innodb_cb_trx_commit(
931+
conn_data->crsr_trx);
932+
}
933+
918934
ib_cb_trx_start(conn_data->crsr_trx,
919935
engine->trx_level,
920936
true, false, NULL);

storage/innobase/api/api0api.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,21 @@ ib_trx_begin(
595595
return(static_cast<ib_trx_t>(trx));
596596
}
597597

598+
599+
/*****************************************************************//**
600+
Check if transaction is read_only
601+
@return transaction read_only status */
602+
UNIV_INTERN
603+
ib_u32_t
604+
ib_trx_read_only(
605+
/*=============*/
606+
ib_trx_t ib_trx) /*!< in: trx handle */
607+
{
608+
trx_t* trx = (trx_t*) ib_trx;
609+
610+
return(trx->read_only);
611+
}
612+
598613
/*****************************************************************//**
599614
Get the transaction's state.
600615
@return transaction state */

storage/innobase/handler/ha_innodb.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ ib_cb_t innodb_api_cb[] = {
482482
(ib_cb_t) ib_get_idx_field_name,
483483
(ib_cb_t) ib_trx_get_start_time,
484484
(ib_cb_t) ib_cfg_bk_commit_interval,
485-
(ib_cb_t) ib_cursor_stmt_begin
485+
(ib_cb_t) ib_cursor_stmt_begin,
486+
(ib_cb_t) ib_trx_read_only
486487
};
487488

488489
/*************************************************************//**

storage/innobase/include/api0api.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
44
55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -494,6 +494,14 @@ ib_trx_state(
494494
/*=========*/
495495
ib_trx_t ib_trx); /*!< in: trx handle */
496496

497+
498+
/*****************************************************************//**
499+
Check if the transaction is read_only */
500+
ib_u32_t
501+
ib_trx_read_only(
502+
/*=============*/
503+
ib_trx_t ib_trx); /*!< in: trx handle */
504+
497505
/*****************************************************************//**
498506
Release the resources of the transaction. If the transaction was
499507
selected as a victim by InnoDB and rolled back then use this function

0 commit comments

Comments
 (0)