MyISAM在某些条件下允许并发插入下读取,并且它让你可以“高度”某些操作,以尽可能少地阻止工作。
MyISAM如何删除和插入行??
删除操作不会重新安排整个表,它们只是把行标记为已经删除,并且在表中留下了一些“洞”。MyISAM在可能的情况下会优先使用这些“洞”,为插入复用空间。如果表是完整的,它就会把新的行拼接在表的最后。
即使MyISAM有表级别的锁,它也能在读取的同时把行拼接到表尾。它通过禁止读取最后一行做到了这一点。这避免了不连续的读取。
但是,当表中间的数据改变的时候,要提供连续读取就困难得多。MVCC是最通用的解决这个问题的方法,它在创建新版本数据的同时提供老版本数据读取。
MyISAM不支持MVCC,所以它只有到达表尾的时候才允许并发插入。
可以使用concurrent_insert变量配置MyISAM的并发插入行为,它有下面的值:
0 MyISAM不允许并发插入,每一次插入都会把表锁住
1 默认值。只要表中没有空缺,MyISAM就允许并发插入
2 该值在MyISAM5.0及更高的版本可用。它强制并发插入到表尾,即使表在空缺也不例外。如果没有线程从表中读取数据,MysQL就会把新数据插入到空缺中。使用了该设置,表的碎片会增多,所以就需要更经常地对表进行优化。
可以配置MySQL把一些操作延迟,然后合并到一起执行。例如,可以使用delay_key_write延迟写入索引。这会带来一些明显的矛盾,立即写入索引(安全但是代价很高),或者等待写入并希望在写入前不要断电(更快,但是如果断电的话就会导致大规模的索引的损坏,因为索引文件已经明显过期了)。也可以使用low_priorite_updates让insert,replace,delete用update比select的优先级更低。这等同于全局地给update使用low_priority修饰符。
MySQL提供了几个语句调节符,允许你修改它的调度策略:
· LOW_PRIORITY关键字应用于DELETE、INSERT、LOAD DATA、REPLACE和UPDATE。
· HIGH_PRIORITY关键字应用于SELECT和INSERT语句。
· DELAYED关键字应用于INSERT和REPLACE语句。
LOW_PRIORITY和HIGH_PRIORITY调节符影响那些使用数据表锁的存储引擎(例如MyISAM和MEMORY)。DELAYED调节符作用于MyISAM和MEMORY数据表。
改变语句调度的优先级
LOW_PRIORITY关键字影响DELETE、INSERT、LOAD DATA、REPLACE和UPDATE语句的执行调度。通常情况下,某张数据表正在被读取的时候,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作)。如果写入者正在等待的时候,另一个读取操作到达了,该读取操作也会被阻塞(block),因为默认的调度策略是写入者优先于读取者。当第一个读取者完成操作的时候,写入者开始操作,并且直到该写入者完成操作,第二个读取者才开始操作。
如果写入操作是一个LOW_PRIORITY(低优先级)请求,那么系统就不会认为它的优先级高于读取操作。在这种情况下,如果写入者在等待的时候,第二个读取者到达了,那么就允许第二个读取者插到写入者之前。只有在没有其它的读取者的时候,才允许写入者开始操作。理论上,这种调度修改暗示着,可能存在LOW_PRIORITY写入操作永远被阻塞的情况。如果前面的读取操作在进行的过程中一直有其它的读取操作到达,那么新的请求都会插入到LOW_PRIORITY写入操作之前。
SELECT查询的HIGH_PRIORITY(高优先级)关键字也类似。它允许SELECT插入正在等待的写入操作之前,即使在正常情况下写入操作的优先级更高。另外一种影响是,高优先级的SELECT在正常的SELECT语句之前执行,因为这些语句会被写入操作阻塞。
如果你希望所有支持LOW_PRIORITY选项的语句都默认地按照低优先级来处理,那么请使用--low-priority-updates选项来启动服务器。通过使用INSERT HIGH_PRIORITY来把INSERT语句提高到正常的写入优先级,可以消除该选项对单个INSERT语句的影响。