我们有一个大的MyISAM表,行只能插入到表的底部。
在做一些基准时,我意识到选择不会(总是)锁定同一个表的其他插入。但是,当插入来自存储过程/函数时,它们将被选择锁定。
为什么?
要演示此行为:
CREATE TABLE Foo (
ID INT NOT NULL AUTO_INCREMENT,
Bar VARCHAR(200),
PRIMARY KEY(ID)) ENGINE=MyISAM;
--INSERT into Foo 10M rows
DELIMITER $$
DROP PROCEDURE IF EXISTS InsertProc$$
CREATE PROCEDURE InsertProc(IN vBar VARCHAR(255))
BEGIN
INSERT Foo(Bar) VALUES (vBar);
END$$
DELIMITER ;
运行以下查询:
SELECT Count(*) FROM Foo WHERE INSTR(Bar, 'abcdefg') > 0;
当Select正在运行时,打开一个新连接并运行以下插入查询:
INSERT Foo(Bar) VALUES ('xyz1234');
该Insert将立即运行并返回,但是如果我运行以下查询:
CALL InsertProc('xyz1234');
现在查询将锁定并等待select完成。
在Window Server 2K3上运行的MySql版本:5.0.51
谢谢。
- 更新 以下是配置文件输出:
直接插入:
(initialization) 0.0000432
checking permissions 0.0000074
Opening tables 0.0000077
System lock 0.0000032
Table lock 0.0000025
init 0.000021
update 0.0002365
end 0.0000382
query end 0.000002
freeing items 0.0000057
closing tables 0.0000022
logging slow query 0.0000005
通过程序插入:
(initialization) 0.0000285
Opening tables 0.0004325
System lock 0.0000022
Table lock 0.0002957
checking permissions 0.0000047
Opening tables 0.000004
System lock 0.0000017
Table lock 3.2365122
init 0.0000422
update 0.000251
end 0.0000025
query end 0.000003
closing tables 0.00004
query end 0.0000074
freeing items 0.0000074
logging slow query 0.000001
cleaning up 0.5790915
为什么程序打开并且“表锁定”两次?
答案 0 :(得分:1)
MyIASM出于任何特殊原因? InnoDB表通常具有更好的锁定特性。
答案 1 :(得分:1)
此问题已作为错误提交: http://bugs.mysql.com/bug.php?id=58689
答案 2 :(得分:0)
猜测:当使用存储过程时,MyISAM表上AUTO_INCREMENT
字段上的锁定/互斥锁处理可能更严格。
要排除这种情况,您是否可以设置ID
不是AUTO_INCREMENT
字段的测试?
如果您的应用程序允许,您是否尝试过INSERT DELAYED?