这几天发现客户那里的mysql集群有时插入特别的慢,通过慢查询日志以及pt-query-digest得知主要是对一张
表的插入特别的慢。 这张表的数据量大概有3百多万行,插入操作特别的频繁。
通过开启innodb monitor得知, 并行的插入操作都阻塞在一个地方:
--Thread 1284204864 has waited at dict0boot.ic line 45 for 305.00 seconds the semaphore:
Mutex at 0x2ac80a08 created file dict0dict.c line 698, lock var 1
通过查看mysql代码得知,他们都在等待一个全局的字典锁
原因是innodb 使用聚集索引来组织数据, 如果要插入的表没有主键或非空的唯一键的话, innodb就会从全局
为这行分配一个row_id。 由于是全局锁,非常的影响插入性能。
何登成有一篇blog很好地分析了这个问题:
http://www.mysqlops.com/2011/12/05/innodb-without-key.html
解决方案:
提供给客户现场的解决方案是添加一个自增列为主键。
由于是个主从复制集群,添加自增列比较麻烦,如果应用允许的话,最好的办法是把原表drop掉,然后重建这张表,再导入数据。因为通过alter添加自增列的操作是复制不安全的。
Adding an AUTO_INCREMENT
column to a table with ALTER TABLE
might not produce the same ordering of the rows on the slave and the master. This occurs because the order in which the rows are numbered depends on the specific storage engine used for the table and the order in which the rows were inserted. If it is important to have the same order on the master and slave, the rows must be ordered before assigning an AUTO_INCREMENT
number. Assuming that you want to add an AUTO_INCREMENT
column to a table t1
that has columns col1
and col2
, the following statements produce a new table t2
identical to t1
but with an AUTO_INCREMENT
column:
CREATE TABLE t2 LIKE t1; ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY; INSERT INTO t2 SELECT * FROM t1 ORDER BY col1, col2;
To guarantee the same ordering on both master and slave, the ORDER BY
clause must name all columns of t1
.
转载请注明转自高孝鑫的博客