继续回答星球水友的问题:沉老师,MyISAM只支持表锁,但是网上有文章说并发插入量比较大的时候用MyISAM比较合适。这矛盾吗?这道题涉及到MySQL表锁的一??些细节,借用这道题,系统的解释一下表锁的“为什么”。画外音:网上很多文章只讲结论,不讲为什么,容易让人迷惑。系统梳理MySQL表锁知识。哪些存储引擎使用表锁?MySQL,除了InnoDB支持行锁,MySQL的其他存储引擎只使用表锁,比如MyISAM、MEMORY、MERGE等,表锁有什么好处呢?表锁占用内存少很多,行锁的个数与行记录数有关,内存消耗大;如果业务经常读写表中很大一部分数据,表锁会更快,因为它只涉及一个锁,而不是同时管理N多个锁;如果业务经常使用groupby,表锁会更快,道理同(2);画外音:在某些这样的场景中,使用MyISAM比使用InnoDB更好。表锁是如何工作的?类似于其他关键资源的读写锁。写的时候加写锁:如果表没有锁,给表加写锁;否则,进入写锁队列;读时,加读锁:如果表没有写锁,则给表加读锁;否则,进入读锁Lock队列;释放表锁时:如果写锁队列和读锁队列中都有锁,写的优先级高,即写锁队列先出队。这样做的原因是,如果有“大查询”,可能会导致写锁分批“饿死”,写锁往往很快就被释放了。画外音:潜台词是,如果有大量并发的更新请求,select会等到所有的更新请求都执行完了再执行。如何查看表锁情况?如果要分析表锁冲突情况,可以查看:Table_locks_immediate:立即获得的表锁数;table_locks_waited:需要等待表锁的次数;这两个变量。使用如下命令查看:showstatuslike'Table%';如果等待表锁的次数比较多,说明表锁可能是一个潜在的瓶颈。说了半天,还是没有进入正题。为什么并发插入量比较大的时候更适合用MyISAM呢?表锁频繁冲突会不会导致吞吐量下降?画外音:系统的知识,比问题的答案更重要。知识点1:MyISAM索引和记录存储是分开的,有单独的区域存放行记录,PK是非聚集索引。知识点2:MyISAM表,如果数据文件(datafile)存储紧密,中间没有freeblocks,数据总是插入到数据文件的末尾(end),就像追加日志一样,性能是很高。当并发插入和选择未被锁定(lockfree)时。如上图所示:数据文件连续紧密存储;并发插入没有表锁争用(只是插入队列互斥);插入仅在数据文件的末尾执行;concurrentselects也可以同时执行(共享读锁);知识点3:对于MyISAM表,如果数据文件中间有空洞,上述机制会失效,直到空洞被新数据填充,解锁机制将再次启用。空洞是怎么造成的?删除或修改数据可能会导致漏洞。如上图所示:中间删除了一些数据,导致中间有空闲块;此时select和insert会出现表锁冲突,不能并发;空闲块再次被填充;这时候并发select和insert恢复了;结语虽然MyISAM只支持表锁,但是上面的机制让MyISAM表锁在高并发select和insert的业务场景下依然有非常强的性能。画外音:本文基于MySQL5.6。希望这能回答你朋友的问题。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
