绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
Compact详述
2020-04-29 17:39:57

前序:
由于业务原因,需要将过期数据删除,之前也已经写了一篇关于如何定期删除数据的文章,但有一个问题出现了,
频繁删除数据之后,会产生很多磁盘碎片,这些碎片进而会影响查询性能,随需要处理之
有好几种方法处理:
  1. 使用compact命令
  2. 重建collection,(将数据导出导入到一个新集合中,然后删除旧集合,重命名新集合)
  3. 新加一个secondary节点,然后将此节点切换为primary

后两种方法以后有时间再细说,也是网友提供的,今天只看Compact命令的实现

简介:
     官方解释是:compact命令能够重写和重组集合的data和index
     格式:      
    { compact: <collection name>,force:<boolen> }    ---红色部分是可选项 
     compact命令之后写你想要整理的collection名字
     force参数用于replica set中primary整理时之用,否则会报错
影响:
compact 一个集合时,会在集合所在的DB上加一个互斥写锁,会导致DB上的所有读写都阻塞,compact执行时间的长短和集合的数据量大小相关,建议在业务低峰时操作;

compact检测机制:
compact命令发出后,其实终是由存储引擎wiredTiger来完成,在执行期间,会不断将集合文件后面的数据往前面空闲的空间写,然后逐步truncate文件回收物理空间;每一轮compact前,WiredTiger都会做如下检查:
  • 前面80%的空间里,是否有20%的空闲空间,用于写入文件后面的20%的数据,或
  • 前面90%的空间里,是否有10%的空闲空间,用于写入文件后面的10%的数据;
如果上述两条一条都不满足,那么执行compact肯定无法回收10%的空闲空间,此时compact就会退出执行,所以有时候对一个大集合执行了compact后很快得到ok:1,且集合空间变化不大, 那么说明此集合可能没有收缩的余地,没有必要执行compact

预估可回收空间
可通过命令db.collname.stats().wiredTiger["block-manager"] 查看
rs1:PRIMARY> db.MsgResultDto.stats().wiredTiger["block-manager"]
{
    "allocations requiring file extension" : 0,
    "blocks allocated" : 8559169,
    "blocks freed" : 3750452,
    "checkpoint size" : 99337433088,
    "file allocation unit size" : 4096,
    "file bytes available for reuse" : 31563096064,    ---表示集合可被回收的空闲空间
    "file magic number" : 120897,
    "file major version number" : 1,
    "file size in bytes" : 130900664320,
    "minor version number" : 0
}



说明:
          在compact期间会阻塞其他针对此collection的操作,所以好在业务不繁忙的时候进行compact动作;
          针对compact完成之后,不同引擎会有不同的磁盘影响
     WireTiger引擎:
          在此引擎的数据库下,compact会整理碎片,并且释放未使用的磁盘空间给系统
     MMAPv1引擎:
          在此引擎的数据库下,compact会整理碎片,重建索引,但不会将未使用的空间释放给系统,后续新插入的数据依然可以使用这些空间
     在复制集架构下的一些注意:
          compact命令不会自动复制到secondary节点执行,compact在每个节点成员中都是独立的,在Primary,secondary中执行时都要使用force参数,
          当在secondary的collection上执行compact命令时,此secondary节点会变成RECOVERING状态,且无法提供读操作
     在capped collection中不必使用compact命令,因为它本身就是固定空间
测试验证:
     在单实例情况下:
     
     
     在复制集架构primary上使用时,如果不使用force参数,则会报错,如下:
          

注意:
在库层面将会持有一个X的独享锁W,且此时compact命令是在一个Secondary节点上执行,则其状态将会变为RECOVERING
rs1:RECOVERING> db.currentOp({"ns" : "APP_MSG_GW.MsgResultDto"})
......
"locks" : {
                "Global" : "w",
                "Database" : "W"
            },
            "waitingForLock" : false,
            "lockStats" : {
                "Global" : {
                    "acquireCount" : {
                        "r" : NumberLong(1),
                        "w" : NumberLong(1)
                    }
                },
                "Database" : {
                    "acquireCount" : {
                        "W" : NumberLong(1)
                    }
                }
            }


......
另起一个session,执行show tables命令也会被阻塞掉
rs1:RECOVERING> rs.slaveOk()
rs1:RECOVERING> show tables;    ---处于阻塞中
。。。


且此时也会阻塞其他用户的登录,会被阻塞登录;
此时执行compact节点会停止同步oplog,产生delay延迟




分享好友

分享这个小栈给你的朋友们,一起进步吧。

IT人士养老之道
创建时间:2019-03-13 15:28:19
作为IT成功人士,30年以后的你如何养老?如何养生?一起聊聊吧
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 小雨滴
    栈主

小栈成员

查看更多
  • 老七
  • 一号管理员
  • qingduyu
  • Bsolar
戳我,来吐槽~