Bug #73168 locking/unlocking overhead for THD::LOCK_thd_data
| Submitted: | 2 Jul 2014 4:14 | Modified: | 2 Jul 2014 11:15 |
|---|---|---|---|
| Reporter: | liu hickey (OCA) | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: InnoDB storage engine | Severity: | S5 (Performance) |
| Version: | 5.6/5.7 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | LOCK_thd_data, set_query | ||
[2 Jul 2014 11:15]
MySQL Verification Team
Hello Liu, Thank you for the report. I observed this while using sysbench // 5.6.20 with defaults settings // mysqld with --performance_schema_instrument='wait/synch/mutex/%=on' ** set up proper consumers // Sysbench [root@cluster-repo mysql-advanced-5.6.20]# sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=dbtest --mysql-user=root --mysql-socket=/tmp/72720M/72720M.sock prepare sysbench 0.4.12: multi-threaded system evaluation benchmark No DB drivers specified, using mysql Creating table 'sbtest'... Creating 1000000 records in table 'sbtest'... [root@cluster-repo mysql-advanced-5.6.20]# sysbench --test=oltp --oltp-test-mode=complex --oltp-read-only=off --oltp-table-size=1000000 --num-threads=900 --max-time=360 --max-requests=0 --mysql-db=dbtest --mysql-user=root --mysql-socket=/tmp/72720M/72720M.sock run sysbench 0.4.12: multi-threaded system evaluation benchmark No DB drivers specified, using mysql Running the test with following options: Number of threads: 900 Doing OLTP test. Running mixed OLTP test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! // mysql> select version(); +---------------------------------------+ | version() | +---------------------------------------+ | 5.6.20-enterprise-commercial-advanced | +---------------------------------------+ 1 row in set (0.00 sec) mysql> use performance_schema;select e.EVENT_NAME, e.SOURCE, e.OPERATION, count(*) as cnt from events_waits_current e join threads t using(thread_id) where type='foreground' and processlist_id not in (1, @@pseudo_thread_id) group by e.EVENT_NAME, e.SOURCE, e.OPERATION order by cnt desc; Database changed +-----------------------------------------+-------------------+-----------+-----+ | EVENT_NAME | SOURCE | OPERATION | cnt | +-----------------------------------------+-------------------+-----------+-----+ | wait/synch/mutex/sql/THD::LOCK_thd_data | sql_class.cc:4467 | lock | 250 | | idle | mysqld.cc:935 | idle | 89 | | wait/synch/mutex/sql/LOCK_open | sql_base.cc:2936 | lock | 36 | | wait/synch/mutex/sql/THD::LOCK_thd_data | sql_class.h:3983 | lock | 4 | | wait/synch/mutex/innodb/dict_sys_mutex | dict0dict.cc:1026 | lock | 3 | | wait/io/table/sql/handler | handler.cc:2788 | fetch | 1 | +-----------------------------------------+-------------------+-----------+-----+ 6 rows in set (0.08 sec) Thanks, Umesh
[25 Feb 2015 10:51]
MySQL Verification Team
Hello Liu, Could you please provide more details about real performance impact? Do you have any test case/ real time stats which confirms the performance impact etc? Thanks, Umesh
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.040 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: For LOCK_thd_data mutex, it's major used to protect thd->query and thd->query_length, accessed from other SHOW related threads: /** Protects THD data accessed from other threads: - thd->query and thd->query_length (used by SHOW ENGINE INNODB STATUS and SHOW PROCESSLIST - thd->mysys_var (used by KILL statement and shutdown). Is locked when THD is deleted. */ mysql_mutex_t LOCK_thd_data; While seen from the PS, it's called too much for normal workload, and major in THD::set_query_xx(): root@performance_schema 05:35:59>select e.EVENT_NAME, e.SOURCE, e.OPERATION, count(*) as cnt from events_waits_current e join threads t using(thread_id) where type='foreground' and processlist_id not in (1, @@pseudo_thread_id) group by e.EVENT_NAME, e.SOURCE, e.OPERATION order by cnt desc; +-----------------------------------------+-------------------+-------------+------+ | EVENT_NAME | SOURCE | OPERATION | cnt | +-----------------------------------------+-------------------+-------------+------+ | wait/synch/mutex/sql/THD::LOCK_thd_data | sql_class.cc:4662 | lock | 3992 | | wait/io/file/innodb/innodb_log_file | fil0fil.cc:5895 | sync | 2 | | wait/io/table/sql/handler | handler.cc:7347 | insert | 2 | | wait/synch/mutex/sql/THD::LOCK_thd_data | sql_base.cc:1492 | lock | 1 | | wait/lock/table/sql/handler | thr_lock.c:556 | read normal | 1 | | wait/io/table/sql/handler | handler.cc:2868 | fetch | 1 | | wait/io/table/sql/handler | handler.cc:2833 | fetch | 1 | +-----------------------------------------+-------------------+-------------+------+ I added some counter stats for THD::set_query_xxx() and found THD::set_query() is executed 87173.2 per second! $gdb -p 113129 -ex " set pagination 0" -ex "print nq" -ex "print nqi" -ex "print ni" -batch && sleep 5 && gdb -p 113129 -ex " set pagination 0" -ex "print nq" -ex "print nqi" -ex "print ni" -batch $1 = 4972652 $2 = 0 $3 = 2486397 $1 = 5408518 $2 = 0 $3 = 2704340 After remove the locking/unlocking in THD::set_query_xxx(), and re-run the load, this mutex has gone in PS: root@performance_schema 07:14:16>select e.EVENT_NAME, e.SOURCE, e.OPERATION, count(*) as cnt from events_waits_current e join threads t using(thread_id) where type='foreground' and processlist_id not in (1, @@pseudo_thread_id) group by e.EVENT_NAME, e.SOURCE, e.OPERATION order by cnt desc; +-------------------------------------+-------------------+-------------------+------+ | EVENT_NAME | SOURCE | OPERATION | cnt | +-------------------------------------+-------------------+-------------------+------+ | idle | mysqld.cc:952 | idle | 3415 | | wait/io/file/sql/binlog | mf_iocache.c:1788 | write | 525 | | wait/io/file/innodb/innodb_log_file | fil0fil.cc:5701 | write | 34 | | wait/io/table/sql/handler | handler.cc:2833 | fetch | 8 | | wait/io/table/sql/handler | handler.cc:2868 | fetch | 8 | | wait/io/table/sql/handler | handler.cc:7347 | insert | 5 | | wait/lock/table/sql/handler | thr_lock.c:556 | write allow write | 3 | | wait/io/table/sql/handler | handler.cc:2992 | fetch | 1 | | wait/io/file/sql/binlog | binlog.cc:6655 | sync | 1 | +-------------------------------------+-------------------+-------------------+------+ 9 rows in set (2.14 sec) How to repeat: PS monitor Suggested fix: As the THD::set_query_xxx() is only conflicts with mysqld_list_processes(SHOW PROCESSLIST) and fill_schema_processlist (SHOW ENGINE INNODB STATUS), we can benefit with less overhead if replace mutex with lock-free atomic operations.