Skip to content

Commit bd8eb01

Browse files
Debarun Banerjeedahlerlend
authored andcommitted
BUG#27661171 INNODB: TRX->DECLARED_TO_BE_INSIDE_INNODB
Problem : -------- We enter innodb in partition row write to order Auto INC partition lock after Innodb. In Innodb we would try re-enter independently. This works fine as long as we have enough tickets left. While performing bulk load we could consume all innodb tickets [innodb_concurrency_tickets = 5000 by default] within same statement. If the partition write happens to consume the last ticket, we face this issue trying to enter once again in innobase write. Solution : ---------- No need to enter innodb in partition write if there are tickets left. 1. We avoid consuming the last ticket as there could be another enter call from innobase. 2. If we enter innodb here, there is at least one more ticket left as the minimum value for "innodb_concurrency_tickets" is 1. Reviewed-by: Jimmy Yang <Jimmy.Yang@oracle.com> RB: 19092
1 parent 94113c9 commit bd8eb01

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

mysql-test/suite/innodb/r/innodb_thread_concurrency_debug.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Setup connections
22
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
3+
SET @old_innodb_concurrency_tickets := @@innodb_concurrency_tickets;
34
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
45
#
56
# Bug #19386426 SHUTDOWN HANGS: CLIENT THREAD IN A LOOP
@@ -75,7 +76,24 @@ col1 col2
7576
2 20
7677
3 30
7778
DROP TABLE t1;
79+
#
80+
# bug#27661171 INNODB: TRX->DECLARED_TO_BE_INSIDE_INNODB
81+
#
82+
CREATE TABLE t1 (col1 INT AUTO_INCREMENT PRIMARY KEY, col2 int)
83+
PARTITION BY KEY(col1) PARTITIONS 2;
84+
# Insert 2 rows in same statement consuming the tickets
85+
SET GLOBAL innodb_concurrency_tickets = 2;
86+
SHOW VARIABLES LIKE 'innodb_concurrency_tickets';
87+
Variable_name Value
88+
innodb_concurrency_tickets 2
89+
INSERT INTO t1(col2) VALUES (10), (20);
90+
SELECT * FROM t1 ORDER BY col1;
91+
col1 col2
92+
1 10
93+
2 20
94+
DROP TABLE t1;
7895
# Cleanup
7996
SET DEBUG_SYNC='reset';
8097
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
98+
SET GLOBAL innodb_concurrency_tickets = @old_innodb_concurrency_tickets;
8199
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;

mysql-test/suite/innodb/t/innodb_thread_concurrency_debug.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
--echo # Setup connections
66
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
7+
SET @old_innodb_concurrency_tickets := @@innodb_concurrency_tickets;
78
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
89

910
connect (con1, localhost, root);
@@ -115,12 +116,27 @@ connection con1;
115116
SELECT * FROM t1 ORDER BY col1;
116117
DROP TABLE t1;
117118

119+
--echo #
120+
--echo # bug#27661171 INNODB: TRX->DECLARED_TO_BE_INSIDE_INNODB
121+
--echo #
122+
CREATE TABLE t1 (col1 INT AUTO_INCREMENT PRIMARY KEY, col2 int)
123+
PARTITION BY KEY(col1) PARTITIONS 2;
124+
125+
--echo # Insert 2 rows in same statement consuming the tickets
126+
SET GLOBAL innodb_concurrency_tickets = 2;
127+
SHOW VARIABLES LIKE 'innodb_concurrency_tickets';
128+
INSERT INTO t1(col2) VALUES (10), (20);
129+
130+
SELECT * FROM t1 ORDER BY col1;
131+
DROP TABLE t1;
132+
118133
--echo # Cleanup
119134
disconnect con1;
120135
disconnect con2;
121136

122137
SET DEBUG_SYNC='reset';
123138
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
139+
SET GLOBAL innodb_concurrency_tickets = @old_innodb_concurrency_tickets;
124140
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;
125141

126142
--source include/wait_until_count_sessions.inc

storage/innobase/handler/ha_innopart.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -958,9 +958,30 @@ class ha_innopart : public ha_innobase,
958958
thr_lock_type lock_type);
959959

960960
int write_row(uchar *record) {
961-
srv_concurrency_enter();
961+
bool entered = false;
962+
auto trx = m_prebuilt->trx;
963+
964+
/* Enter innodb to order Auto INC partition lock after Innodb. No need to
965+
enter if there are tickets left. Currently we cannot handle re-enter
966+
without exit if no more tickets left.
967+
968+
1. We avoid consuming the last ticket as there could be another enter
969+
call from innobase.
970+
971+
2. If we enter innodb here, there is at least one more ticket left as
972+
the minimum value for "innodb_concurrency_tickets" is 1 */
973+
974+
if (!trx->declared_to_be_inside_innodb) {
975+
srv_concurrency_enter();
976+
entered = true;
977+
}
978+
962979
auto err = Partition_helper::ph_write_row(record);
963-
srv_concurrency_exit();
980+
981+
if (entered) {
982+
srv_concurrency_exit();
983+
}
984+
964985
return (err);
965986
}
966987

0 commit comments

Comments
 (0)