数据库存储说明
给一条书目记录上传对象 数据库是链表结构,比如划成4k,4096的块,如果要分配记录在4096以下就给一块,如果在4097,比4096多一个字符,那就分2块4096的。举个例子,比如某个公司,给一个员工分了一套三居室的房子,但是要住中间的房间,后来又来了一个员工,那这套三居室有2个房间有人住了,再来一个员工,那这套三居室就住满了。如果再来第四个员工,那就重新分配一套三居室的房间,还是要住满。数据库是按照块来管理的,你往数据库中存1个字节,它是不会给你分1个字节的空间,而是直接分4096,这时候修改这条记录,不断扩大它,把它改成2个字节,3个字节,4个字节,它都是4096。等到这条记录变成4097了,那么占得空间大小就变为4096*2了。 如果删除完了,占1个4096或者多个,这个块也是个链表,专门有一个垃圾站废物链表,就把它收集起来了,但没有还给操作系统,这就是为什么存储到数据库数据目录下的文件,在书目对象下删除了这条记录后依旧没有释放空间。比如上传的记录为1个G,那么用windows操作系统看对应的文件夹,它就是1个G,在书目下删除这个对象记录,它还是1个G,只要你往里面上传的记录大小不超过1个G,它永远就占这么大的空间。等于说这个空间,微软的sql server已经拿到了,但是没还给操作系统,但确实是删除了
测试,给一条书目上传记录,存到了object目录下,然后在dp2内务删除这条记录,查看object目录下该文件是否存在?实际测试结果为不存在了,文件被删除。
普通的书目记录叫00000000\001,对象如果属于它就是00000000\001_0、00000000\001_1,这样的命名方式,是跟对象中某一记录的file元素的id是对应的。 前面7位数字是目录,后面3位是文件名,加在一起是10位。因为操作系统记录了成千上万个文件,找它非常的慢,相当于门牌号一样。每个目录,例如0000000中只有3位数,每条目录中最多有999个记录, 这样算起来记录数就少多了,可以把数据库中几万条对象文件分成一片一片的子目录,这样能提高每次写入,读取的运行速度。
操作系统是windows文件系统是NTFS,FAT32有个bug,文件不能太大,U盘不能超过2G,不然会拷不进去。NTFS最大文件上限为2TB。 sql server 数据库为底层时,首先看databases.xml中的配置然后将文件大小分为2拨,并不看sql server的image类型。如果databases.xml中不配置界限,程序一看超过2G不会往数据库里试一下能不能存,而是直接存到object目录中。如果配置了3个G,欺骗了程序,往数据库里面存,但是存到超过了image的最大值了,就中断了,并且会有提示。
oracle,sqlite,mysql都是写入对象文件的,不写入数据库的,操作系统有个2G的问题,过2G也是过个坎。
postgresql数据库bytea字段,比如现在有1k,再给它1k,就追加在后面,但是postgresql非常在意事务性,(事务性是指:这个字段里面原来是1k,现在再往里面写1k,写成功了就是2k。它考虑的是,在写第二个1k,写到一半的时候,如果出现错误,事务要回滚,回滚完之后,把一个完全没有被干扰过的,原样的东西还给你。就等于说,要么成功,2段都写进去了,要么失败以后还原到没写的状态。)
数据库是如何达到事务性的目的? 你不是要追加吗?(以前这条记录就是1k,它把这条记录复制过去,产生一条新纪录,然后在1k上满足要求,追加第2个1k,变成2k。而你看到的是,你在后面追加了1k,而数据库是把原来的记录藏起来,复制了一个新纪录,复制了1k,然后再往后面追加1k,总共操作了3k)
这种操作非常吓人,比如上传对象上传到1个G了,你在后面追加1个G多1K,它先把1G保存起来,然后复制出来产生的记录,第二个1G,然后在这后面加了1K,瞬间磁盘就扩大了1倍。本来上传1个1K,结果产生了1个1G很大的文件,而且这个文件也没有回收,要等到你执行一个回收的命令,才会回收。(微软的sql server不会有这个问题)