当前位置: 首页 > 科技观察

什么存储引擎更适合频繁插入?

时间:2023-03-12 12:35:37 科技观察

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