在分析 LOAD DATA INFILE 语句的 mysql 中,“系统锁”是什么意思?

Dav*_*rks 6 mysql innodb profiler

使用 LOAD DATA INFILE 插入到 innodb 的 2M 行需要 7.5 分钟,分析显示 99% 的时间在“系统锁定”中

这能告诉我什么有用吗?

   mysql> set profiling=1;
   Query OK, 0 rows affected (0.00 sec)

   mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
   Query OK, 1964807 rows affected, 8 warnings (7 min 27.35 sec)
   Records: 1964806  Deleted: 1  Skipped: 0  Warnings: 8

   mysql> show profile for query 1;
   +------------------------------+------------+
   | Status                       | Duration   |
   +------------------------------+------------+
   | starting                     |   0.000206 |
   | checking permissions         |   0.000015 |
   | Opening tables               |   0.000034 |
   | System lock                  | 447.327523 |
   | Waiting for query cache lock |   0.000352 |
   | query end                    |   0.000011 |
   | closing tables               |   0.000014 |
   | freeing items                |   0.000033 |
   | logging slow query           |   0.000007 |
   | logging slow query           |   0.000006 |
   | cleaning up                  |   0.000006 |
   +------------------------------+------------+
   11 rows in set (0.02 sec)
Run Code Online (Sandbox Code Playgroud)

小智 7

mysql_load() 函数调用 open_and_lock_tables() 函数来锁定 LOAD DATA 语句中提到的表。

MySQL 获得表的排他锁,以便它可以非常快速地将数据加载到表中。LOAD DATA 过程中的开销非常小,只需进行最低限度的解析即可使其工作。

CONCURRENT 选项仅影响 MyISAM 表,如果您要加载到 InnoDB 表中,则它不允许并发访问。

System lock花费这么长时间的原因是实际数据加载被集中到了该步骤的计时中。探查器通过测量fenceposts之间的时间来工作,即为每个检测的用户功能记录进入时间。mysql_lock_tables() 函数是从 mysql_load() 内部调用的,但 mysql_load() 没有被检测,所以经过的时间从系统锁开始,到下一个栅栏柱结束,也就是查询缓存锁。

您的 196 万行数据加载大约需要 447 秒,没有任何方法可以将实际锁定时间开销与加载时间分开,因为加载没有被检测。


Rol*_*DBA 5

根据关于通用线程状态MySQL 文档

线程将请求或正在等待表的内部或外部系统锁。如果此状态是由外部锁请求引起的,并且您没有使用多个访问相同 MyISAM 表的 mysqld 服务器,则可以使用 --skip-external-locking 选项禁用外部系统锁。但是,默认情况下外部锁定是禁用的,因此此选项很可能不起作用。对于 SHOW PROFILE,这种状态意味着线程正在请求锁定(而不是等待它)。

这应该不足为奇,因为 InnoDB 执行行级锁定。此外,gen_clust_index(又名聚集索引)在某些时候会在主键上遇到共享锁和排他锁。