Bug #40760 | "set global innodb_thread_concurrency = 0;" is not safe | ||
---|---|---|---|
Submitted: | 15 Nov 2008 18:12 | Modified: | 20 Jun 2010 1:00 |
Reporter: | Yasufumi Kinoshita | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
Version: | 5.0.67, 5.0.70, 5.1 | OS: | Any |
Assigned to: | Inaam Rana | CPU Architecture: | Any |
[15 Nov 2008 18:12]
Yasufumi Kinoshita
[16 Nov 2008 6:16]
Valeriy Kravchuk
Thank you for a problem report. Sorry, but I was not able to repeat the behaviour described neither on 5.0.70 nor on latest 5.0.74 from bzr with only two sessions whith one of them doing "select count(*) from big_innodb_table" or "update big_innodb_table set ...". So, please, provide a more detailed test case. Do I need to use multi-core system to repeat this?
[16 Nov 2008 10:56]
Yasufumi Kinoshita
Valeriy, I think any long query is OK. And it don't need SMP. My test case is intended to change srv_thread_concurrency between these functions at ha_innodb.cc /********************************************************************** Save some CPU by testing the value of srv_thread_concurrency in inline functions. */ inline void innodb_srv_conc_enter_innodb( /*=========================*/ trx_t* trx) /* in: transaction handle */ { if (UNIV_LIKELY(!srv_thread_concurrency)) { /* intended value == 8 */ return; } srv_conc_enter_innodb(trx); } /********************************************************************** Save some CPU by testing the value of srv_thread_concurrency in inline functions. */ inline void innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { if (UNIV_LIKELY(!srv_thread_concurrency)) { /* intended value == 0 */ return; } srv_conc_exit_innodb(trx); } In addition, the another test case to halt is that when benchmark (like DBT-2) is running, repeat to switch "set global innodb_thread_concurrency = 0;" and "set global innodb_thread_concurrency = 8;"(smaller value than the sessions of benchmark) many times.
[16 Nov 2008 11:23]
Valeriy Kravchuk
Verified with 5.0.70 on our sol10-sparc-c based on last comment. I had started 10 long running transactions (INSERT ... SELECT, UPDATE, DELETE) with innodb_thread_concurrency=8 and then, from the other session, did: set global innodb_thread_concurrency=0; set global innodb_thread_concurrency=1; set global innodb_thread_concurrency=4; dozen of times. I've got in the error log eventually: Version: '5.0.70-enterprise-gpl-log' socket: '/tmp/vk.sock' port: 4444 MySQL Enterprise Server (GPL) 081116 12:18:30 InnoDB: Error: Freeing a trx which is declared to be processing InnoDB: inside InnoDB. TRANSACTION 0 23807000, not started, OS thread id 56, thread declared inside InnoDB 49 MySQL thread id 46, query id 373 localhost root
[18 Nov 2008 16:45]
Heikki Tuuri
Thank you Yasufumi. You again found a bug concerned with races. In very old versions of InnoDB, one could not dynamically adjust thread concurrency, and the bug was not present. Hmm... a fix might be that in the two functions below, we test if trx->declared_to_be_inside_innodb is TRUE. If that is the case, we must do the .._exit() regardless of the value of srv_thread_concurrency. That is, in the first function below, replace: " if (UNIV_LIKELY(!srv_thread_concurrency)) {" with: " if (UNIV_LIKELY(!srv_thread_concurrency && !trx->declared_to_be_inside_innodb )) {" In the second function, do a similar replacement. This solves the problem of srv_thread_concurrency > 0 at a thread ENTER and srv_thread_concurrency == 0 at a thread EXIT. What about the inverse problem? I think that problem is already solved in the code of the second function by: " if (trx->declared_to_be_inside_innodb == FALSE) { return; } " /********************************************************************** Save some CPU by testing the value of srv_thread_concurrency in inline functions. */ inline void innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } srv_conc_exit_innodb(trx); } /************************************************************************* This must be called when a thread exits InnoDB in a lock wait or at the end of an SQL statement. */ void srv_conc_force_exit_innodb( /*=======================*/ trx_t* trx) /* in: transaction object associated with the thread */ { srv_conc_slot_t* slot = NULL; if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } if (trx->mysql_thd != NULL && thd_is_replication_slave_thread(trx->mysql_thd)) { return; } if (trx->declared_to_be_inside_innodb == FALSE) { return; } Assigning this to Inaam, who is our race condition man.
[18 Nov 2008 17:12]
Heikki Tuuri
This comment in srv0srv.c is wrong: " lint srv_conc_n_threads = 0; /* number of OS threads currently inside InnoDB; it is not an error if this drops temporarily below zero because we do not demand that every thread increments this, but a thread waiting for a lock decrements this temporarily */ " In the current code, it can never become negative!
[18 Nov 2008 17:51]
Heikki Tuuri
There are invariants, which should be stated in the comment: (1) srv_conc_n_threads is the number of threads that have trx->declared_to_be_inside_innodb == TRUE; (2) trx->declared_to_be_inside_innodb will eventually become FALSE for every thread.
[12 Mar 2009 22:10]
Paul DuBois
Noted in 5.1.32, 6.0.10 changelog. Changing innodb_thread_concurrency at runtime could cause errors.
[17 Jul 2009 16:36]
Mark Callaghan
It would be nice to get a fix for this in 5.0
[5 May 2010 15:04]
Bugs System
Pushed into 5.1.47 (revid:joro@sun.com-20100505145753-ivlt4hclbrjy8eye) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[6 May 2010 16:53]
Paul DuBois
Push resulted from incorporation of InnoDB tree. No changes pertinent to this bug. Re-closing.
[28 May 2010 6:06]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100524190136-egaq7e8zgkwb9aqi) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (pib:16)
[28 May 2010 6:34]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100524190941-nuudpx60if25wsvx) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[28 May 2010 7:02]
Bugs System
Pushed into 5.5.5-m3 (revid:alik@sun.com-20100524185725-c8k5q7v60i5nix3t) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[29 May 2010 23:07]
Paul DuBois
Push resulted from incorporation of InnoDB tree. No changes pertinent to this bug. Re-closing.
[15 Jun 2010 8:09]
Bugs System
Pushed into 5.5.5-m3 (revid:alik@sun.com-20100615080459-smuswd9ooeywcxuc) (version source revid:mmakela@bk-internal.mysql.com-20100415070122-1nxji8ym4mao13ao) (merge vers: 5.1.47) (pib:16)
[15 Jun 2010 8:24]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100615080558-cw01bzdqr1bdmmec) (version source revid:mmakela@bk-internal.mysql.com-20100415070122-1nxji8ym4mao13ao) (pib:16)
[17 Jun 2010 12:11]
Bugs System
Pushed into 5.1.47-ndb-7.0.16 (revid:martin.skold@mysql.com-20100617114014-bva0dy24yyd67697) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[17 Jun 2010 12:58]
Bugs System
Pushed into 5.1.47-ndb-6.2.19 (revid:martin.skold@mysql.com-20100617115448-idrbic6gbki37h1c) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[17 Jun 2010 13:38]
Bugs System
Pushed into 5.1.47-ndb-6.3.35 (revid:martin.skold@mysql.com-20100617114611-61aqbb52j752y116) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)