一、特性介绍
在某些特定的情况下,Myisam引擎支持并发插入(concurrent inserts),以降低读操作和写操作的争用:如果一个myisam表的数据文件中间没有空闲块(free blocks),那么新的数据行将总是被插入到数据文件的末尾,在这种情况下,该myisam表上将允许同时有insert和select操作而不会有锁冲突。也就是说,当myisam表上有其它会话在读取表数据,你也照样可以执行insert操作。
二、concurrent_insert参数
Myisam表中间的数据行被删除或更新,就可能导致空闲块。如果表文件中间有空闲块,那么并发插入特性将不生效,直到空闲块被数据行填满后才自动生效。Myisam引擎的这种行为,可以通过系统变量concurrent_insert来控制:
mysql> show variables like '%concurrent_insert%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| concurrent_insert | AUTO |
+-------------------+-------+
该参数有三个值:never、auto、always。
值为never(或0),不启用并发插入功能;
值为auto(或1),自动模式,当数据文件中间没有空闲块则启用,否则自动取消;
值为always(或2):即便表数据文件中间有空闲块也始终启用并发插入。当有空闲块时,表上有其它会话的读操作,这时新的数据行将被插入到文件的末尾;如果表上没有其它操作,那么insert操作就是一个正常的操作:获得一个写锁,并优先将数据行插入空闲块中。
三、测试示例
在空表myisam_tb中导入了64条数据,无任何删除操作,且表引擎为myisam。在session1上模拟出一个对myisam_tb表的慢查询:
mysql> select *,sleep(1) from myisam_tb where sex='f';
执行时间40s,输出结果忽略
此时在session2上,插入id为65的数据:
mysql> insert into myisam_tb values(65,'he','f',385685.32,'fbbf');
Query OK, 1 row affected (0.01 sec)
可以看到insert语句数据直接可以插入进去,并没有发生锁等待现象。将myisam_tb表中删除中间一部分数据:
mysql> delete from myisam_tb where id between 20 and 40;
Query OK, 21 rows affected (0.01 sec)
再执行慢查询:
mysql> select *,sleep(1) from myisam_tb where sex='f';
另外一个会话上再执行insert语句,插入一条新数据:
mysql> insert into myisam_tb values(66,'he','f',385685.32,'fbbf');
Query OK, 1 row affected (25.57 sec)
可以看到语句执行了25s,这是因为表有空闲块,concurrent_insert参数值为auto,所以出现了锁等待。
将concurrent_insert参数值修改为always:
mysql> show variables like '%concurrent%';
+-------------------+--------+
| Variable_name | Value |
+-------------------+--------+
| concurrent_insert | ALWAYS |
+-------------------+--------+
Session1上再执行一个慢查询:
mysql> select *,sleep(1) from myisam_tb;
执行时间45s,输出结果忽略
session2上插入一条数据:
mysql> insert into myisam_tb values(67,'hgj','f',3232,'bngj');
Query OK, 1 row affected (0.00 sec)
可以看出在concurrent_insert参数值改为always后,即便是有空闲块,新插入的数据也是插在数据文件的末尾。同样也可以实现查询与插入操作并存,不过空闲块空间不会被利用。