精华内容
参与话题
问答
  • 这个ID会是数据库中的唯一主键,在它上面会建立聚集索引!ID生成的核心需求有两点:全局唯一趋势有序二,为什么要全局唯一?著名的例子就是身份证号码,身份证号码确实是对人唯一的,然而一个人是可以办理多个身份证...
    一,题记

    所有的业务系统,都有生成ID的需求,如订单id,商品id,文章ID等。这个ID会是数据库中的唯一主键,在它上面会建立聚集索引!

    ID生成的核心需求有两点:

    • 全局唯一

    • 趋势有序


    二,为什么要全局唯一?


    著名的例子就是身份证号码,身份证号码确实是对人唯一的,然而一个人是可以办理多个身份证的,例如你身份证丢了,又重新补办了一张,号码不变。

    问题来了,因为系统是按照身份证号码做唯一主键的。此时,如果身份证是被盗的情况下,你是没有办法在系统里面注销的,因为新旧2个身份证的“主键”都是身份证号码。

    也就是说,旧的身份证仍然逍遥在外,完全有效。这个时候,还好有一个身份证有效时间的东西,只有靠身份证有效期来辨识了。不过,这就是现在这么多银行,电信诈骗的由来,捡到一张身份证,去很多银行,手机,酒店都可以使用!身份证缺乏注销机制!

    所以,经验告诉我们。不要相信自己的直觉,业务上所谓的唯一往往都是不靠谱的,经不起时间的考研的。所以需要单独设置一个和业务无关的主键,专业术语叫做代理主键(surrogate key)。

    这也是为什么数据库设计范式,唯一主键是第一范式!


    三,为什么要趋势有序


    以mysql为例,InnoDB引擎表是基于B+树的索引组织表(IOT);每个表都需要有一个聚集索引(clustered index);所有的行记录都存储在B+树的叶子节点(leaf pages of the tree);基于聚集索引的增、删、改、查的效率相对是最高的;如下图:

    • 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择其作为聚集索引;

    • 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引;

    • 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

    综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高

    • 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;

    • 该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;

    • 除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。)

    这就是为什么我们的分布式ID一定要是趋势递增的!那么在开发当中,面对这种分布式ID需求,常见的处理方案有哪些呢?


    四,数据库自增长序列或字段


    最常见的方式。利用数据库,全数据库唯一。

    优点:

    1)简单,代码方便,性能可以接受。

    2)数字ID天然排序,对分页或者需要排序的结果很有帮助。

     

    缺点:

    1)不同数据库语法和实现不同,数据库迁移的时候或多数据库版本支持的时候需要处理。

    2)在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险。

    3)在性能达不到要求的情况下,比较难于扩展。

    4)如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦。

    5)分表分库的时候会有麻烦。

    优化方案:

    1)针对主库单点,如果有多个Master库,则每个Master库设置的起始数字不一样,步长一样,可以是Master的个数。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。这样就可以有效生成集群中的唯一ID,也可以大大降低ID生成数据库操作的负载。


    五,UUID


    常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。

    优点:

    1)简单,代码方便。

    2)生成ID性能非常好,基本不会有性能问题。

    3)全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对。

     

    缺点:

    1)没有排序,无法保证趋势递增。

    2)UUID往往是使用字符串存储,查询的效率比较低。

    3)存储空间比较大,如果是海量数据库,就需要考虑存储量的问题。

    4)传输数据量大

    5)不可读。


    六,Redis生成ID


    当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。

    可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:

    A:1,6,11,16,21

    B:2,7,12,17,22

    C:3,8,13,18,23

    D:4,9,14,19,24

    E:5,10,15,20,25

    这个,随便负载到哪个机确定好,未来很难做修改。但是3-5台服务器基本能够满足器上,都可以获得不同的ID。但是步长和初始值一定需要事先需要了。使用Redis集群也可以方式单点故障的问题。

    另外,比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。

     

    优点:

    1)不依赖于数据库,灵活方便,且性能优于数据库。

    2)数字ID天然排序,对分页或者需要排序的结果很有帮助。


    缺点:

    1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

    2)需要编码和配置的工作量比较大。


    七,twitter


    twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局唯一ID生成服务:Snowflake。
    1 41位的时间序列(精确到毫秒,41位的长度可以使用69年)
    2 10位的机器标识(10位的长度最多支持部署1024个节点) 
    3 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) 最高位是符号位,始终为0。
    优点:


    • 高性能,低延迟;独立的应用;

    • 按时间有序。 


    缺点:

    • 需要独立的开发和部署。

    • 强依赖时钟,如果主机时间回拨,则会造成重复ID,会产生

    • ID虽然有序,但是不连续

    原理


    八,MongoDB的ObjectId


    MongoDB的ObjectId和snowflake算法类似。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。MongoDB 从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。使其在分片环境中要容易生成得多。

    ObjectId使用12字节的存储空间,其生成方式如下:

    |0|1|2|3|4|5|6 |7|8|9|10|11|

    |时间戳 |机器ID|PID|计数器 |

    前四个字节时间戳是从标准纪元开始的时间戳,单位为秒,有如下特性:

     1 时间戳与后边5个字节一块,保证秒级别的唯一性;
     2 保证插入顺序大致按时间排序;
     3 隐含了文档创建时间;
     4 时间戳的实际值并不重要,不需要对服务器之间的时间进行同步(因为加上机器ID和进程ID已保证此值唯一,唯一性是ObjectId的最终诉求)。

    机器ID是服务器主机标识,通常是机器主机名的散列值。

    同一台机器上可以运行多个mongod实例,因此也需要加入进程标识符PID。

    前9个字节保证了同一秒钟不同机器不同进程产生的ObjectId的唯一性。后三个字节是一个自动增加的计数器(一个mongod进程需要一个全局的计数器),保证同一秒的ObjectId是唯一的。同一秒钟最多允许每个进程拥有(256^3 = 16777216)个不同的ObjectId。

    总结一下:时间戳保证秒级唯一,机器ID保证设计时考虑分布式,避免时钟同步,PID保证同一台服务器运行多个mongod实例时的唯一性,最后的计数器保证同一秒内的唯一性(选用几个字节既要考虑存储的经济性,也要考虑并发性能的上限)。

    “_id”既可以在服务器端生成也可以在客户端生成,在客户端生成可以降低服务器端的压力。


    九,类snowflake算法


    国内有很多厂家基于snowflake算法进行了国产化,例如

    百度的uid-generator:

    https://github.com/baidu/uid-generator

    美团Leaf:

    https://github.com/zhuzhong/idleaf

    基本是对snowflake的进一步优化,比如解决时钟 回拨问题!


    十,总结


    总体而言,分布式唯一ID需要满足以下条件:

    • 高可用性:不能有单点故障。

    • 全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。

    • 趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。

    • 时间有序:以时间为序,或者ID里包含时间。这样一是可以少一个索引,二是冷热数据容易分离。

    • 分片支持:可以控制ShardingId。比如某一个用户的文章要放在同一个分片内,这样查询效率高,修改也容易。

    • 单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。

    • 长度适中:不要太长,最好64bit。使用long比较好操作,如果是96bit,那就要各种移位相当的不方便,还有可能有些组件不能支持这么大的ID。

    • 信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞争对手可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。

                </div>
    
    展开全文
  • 访问https://www.51job.com/,在搜索框输入关键字:python java,用右边的加号选择北京、上海、广州、深圳 四个城市,点击搜索按钮,同时谷歌浏览器的开发者工具,详细观察整个过程中http协议的请求以及响应的具体...


    访问https://www.51job.com/,在搜索框输入关键字:python java,用右边的加号选择北京、上海、广州、深圳 四个城市,点击搜索按钮,同时谷歌浏览器的开发者工具,详细观察整个过程中http协议的请求以及响应的具体情况。.网页返回的内容是html格式的,下面是经过简化之后的部分页面内容:
    <span class="t3">北京-朝阳区</span>
    <span class="t4">1.5-2万/月</span>
    <span class="t5">10-16</span>
    <span class="t3">深圳-龙华新区</span>
    <span class="t4">1.5-2.5万/月</span>
    <span class="t5">10-16</span>
    <span class="t3">北京-海淀区</span>
    <span class="t4">0.8-1.5万/月</span>
    <span class="t5">10-16</span>
    <span class="t3">广州</span>
    <span class="t4">1.5-2万/月</span>
    <span class="t5">10-16</span>
    请编写程序取出里面的数据部分,结果应该如下:
    北京-朝阳区
    1.5-2万/月
    10-16
    深圳-龙华新区
    1.5-2.5万/月
    10-16
    北京-海淀区
    0.8-1.5万/月
    10-16
    广州
    1.5-2万/月
    10-16

    分别获取关键字是python、java,右边选择北京、上海、广州、深圳四个城市时前10页的招聘数据,用正则表达式解析获取的数据,按照以下格式把数据存储在文件中
    关键字 工作地点 薪资min 薪资max
    java 上海     1.5     1.6
    java 深圳     1.5     3
    java 上海     0.8     1
    python 北京     1.5     2.5
    python 广州     1.5     2.2

    提示:网页上的数据有两处需要处理:
    一是工作地点,原始内容可能是上海-浦东新区,只保留前面的城市名上海
    二是薪资,原始内容是1.2-1.8万/月或10-20万/年,把单位换算成一致的,并且把最小值和最大值分开存放

    # -*- coding:utf-8 -*-
    import urllib.request
    import re
    import sqlite3
    
    def get_content(page, key):
        url = 'https://search.51job.com/list/010000%252C020000%252C030200%252C040000,000000,0000,00,9,99,' + key + ',2,' + str(page) + '.html'
        a = urllib.request.urlopen(url)
        html = a.read().decode('gbk')
        lst = re.findall(r'<span class="t3">(北京|上海|广州|深圳).*?</span>\s+<span class="t4">(\d+\.?\d?)-(\d+\.?\d?)(万|千)/(年|月)</span>', html)
        return lst
    
    conn = sqlite3.connect('51.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS jobs
            (key text, addr text, min float, max float)''')
    c.execute('''delete from jobs''')
    conn.commit()
    
    with open('51.txt', 'w') as f:
        f.write('%s\t%s\t%s\t%s\n' % ('key','addr','min','max'))
        for key in ('python', 'java'):
            for each in range(1, 11):
                for items in get_content(each, key):
                    min = float(items[1])
                    max = float(items[2])
                    if items[3] == "千":
                        min /= 10
                        max /= 10
                    if items[4] == "年":
                        min /= 12
                        max /= 12
                    f.write('%s\t%s\t%s\t%s\n' % (key, items[0], round(min, 2), round(max, 2)))
                    c.execute("INSERT INTO jobs VALUES (?,?,?,?)", (key, items[0], round(min, 2), round(max, 2)))
    conn.commit()
    conn.close()
    
    if __name__ == '__main__':
        lst = get_content(1, 'python')
        print(lst)
    

     

    展开全文
  • 第二章、数据存储与检索一、代码初始化准备orderform.htmlprocessorder.php当前效果orderform.htmlprocessorder.php二、关于文件创建的知识预备将数据写入一个文件步骤将数据读出文件步骤fopen()函数几种指定文件...

    一、代码初始化准备

    在第一章原有代码的基础上进行一些修改

    orderform.html

    <form action="processorder.php"method="post">
    <table border="0"> 
    <tr bgcolor="#cccc00"> 
    <td width="150">Item</td>
    <td width="15">Quantity</td>
    </tr>
    <tr>
    <td>Tires</td>
    <td align="center">
    <input type="text"name="tireqty"size="3" maxlength="3"/>
    </td>
    </tr>
    <tr>
    <td>Oil</td>
    <td align="center">
    <input type="text"name="oilqty"size="3" maxlength="3"/>
    </td>
    </tr>
    <tr>
    <td>Spark Plugs</td>
    <td align="center">
    <input type="text"name="sparkqty"size="3" maxlength="3"/>
    </td>
    </tr>
    <tr>
    <td>Shipping Address</td>
    <td align="center"> 
    <input tpye="text"name="address"size="20"maxlength="10"/>
    </td>
    
    </tr>
    <tr>
    <td colspan="2"align="center">
    <input type="submit"value="Submit Order"/>
    </td>
    </tr>
    </table>
    </form>
    

    processorder.php

    <?php 
    //create short variable names 
    $tireqty=$_POST['tireqty']; 
    $oilqty=$_POST['oilqty']; 
    $sparkqty=$_POST['sparkqty']; 
    $address=$_POST['address'];
    $date=date('H:i,jS F Y');
    define('TIREPRICE',100); 
    define('OILPRICE',10); 
    define('SPARKPRICE',4);
    ?>
    <html>
    <head>
    <title>Bob's Auto Parts-Order Results</title>
    </head>
    <body>
    <h1>Bob's Auto Parts</h1>
    <h2>Order Results</h2>
    <?php 
    echo"<p>Order processed at";
    echo"</p>";
    echo"<p>Order processed at ".date('H:i,jS F Y')."</p>";
    echo'<p>Your order is as follows:</p>';
    $totalqty=0; 
    $totalqty=$tireqty+$oilqty+$sparkqty;
    echo"Items ordered:".$totalqty."<br/>"; 
    if($totalqty==0){ 
        echo"You did not order anything on the previous page!<br/>"; 
    }else{ 
        if($tireqty>0){ 
            echo$tireqty."tires<br/>"; 
        }if($oilqty>0){ 
            echo$oilqty."bottles of oil<br/>"; 
        }if($sparkqty>0){ 
            echo$sparkqty."spark plugs<br/>"; 
        }
    }
    $totalamount=0.00; 
    $totalamount=$tireqty*TIREPRICE +$oilqty*OILPRICE +$sparkqty*SPARKPRICE; 
    $totalamount=number_format($totalamount,2,'.','');
    echo"<p>Total of order is$".$totalamount."</p>"; 
    echo"<p>Address to ship to is".$address."</p>";
    ?>
    </body> 
    </html>
    

    当前效果

    orderform.html

    在这里插入图片描述

    processorder.php

    在这里插入图片描述

    二、关于文件创建的知识预备

    将数据写入一个文件步骤

    1)打开这个文件。如果文件不存在,需要先创建它。
    2)将数据写入这个文件。
    3)关闭这个文件。

    将数据读出文件步骤

    1)打开这个文件。如果这个文件不能打开(例如,文件不存在),就应该意识到这一 点并且正确地退出。
    2)从文件中读出数据。
    3)关闭这个文件。

    fopen()函数

    $fp=fopen("$DOCUMENT_ROOT/../orders.txt",'w');
    

    第一个参数是要打开的文件,文件名为orders.txt。
    而其中的$DOCUMENT_ROOT,在之前有过赋值为:

    $DOCUMENT_ROOT=$_SERVER['D OCUMENT_ROOT']
    

    等号右边是PHP内置变量,这个变量指向了Web服务器文档树的根。
    “…” 表示文档根目录的父目录。
    第二个参数是是文件模式,指定了将对文件进行的操 作。
    使用最多的几个:
    r:只读;
    w:只写,若文件已有内容,则原先内容会被覆盖;文件不存在则自动新建;
    a:追加,若文件已有内容,则自动从尾部进行写入;文件不存在则自动新建;

    几种指定文件路径的方法实例

    注意 该php文件的位置为:
    在这里插入图片描述
    等号右边是PHP内置变量,这个变量指向了Web服务器文档树的根。(即xampp文档的根–Most important)
    “…” 表示文档根目录的父目录。(即xampp)

    $DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT'];
    $fp=fopen("$DOCUMENT_ROOT/../orders.txt",'ab');
    

    运行后会找到新建文件位置:
    在这里插入图片描述
    没有指定路径,这个文件就将在脚本自身所在的相同目录中查找或者创建。

    $fp=fopen("orders.txt",'ab');
    

    运行后会出现在php所在的文件中:
    在这里插入图片描述
    (不推荐)这样做的问题在于,特别是如果将网站安装在别人的服务器上,这 个绝对路径可能会改变。

    $fp=fopen("D:/Most important/xampp/htdocs/phps file/orders.txt",'ab');
    

    指定绝对路径运行后:
    在这里插入图片描述

    三、通过FTP或HTTP打开文件

    作用:可以使用该函数打开一个远程文件:
    ①如果使用的文件名是以ftp://开始的,fopen()函数将建立一个连接到指定服务器的被动 模式,并返回一个指向文件开始的指针。
    ②如果使用的文件名是以http://开始的,fopen()函数将建立一个到指定服务器的HTTP连 接,并返回一个指向HTTP响应的指针。
    注意 :URL中的域名不区分大小写,但是路径和文件名可能会区分大小写。
    比如,想要以只读模式打开百度的robots.txt文件:

    $fp=fopen("http://www.baidu.com/robots.txt",'r');
    

    四、正式开始

    写入文件

    将系统自带的变量赋予DOCUMENT_ROOT:
    在这里插入图片描述
    新建文件,其中@是抑制系统报错,可以在后续自己手动输入希望回馈的错误:
    在这里插入图片描述
    给文件上锁,以便告诉其它操作:我正在’独占’这个文件,防止其它文件进行操作:
    在这里插入图片描述
    判断文件是否存在,存在则输出echo后面的话:
    在这里插入图片描述
    写入文件(第一个参数是指向文件的指针,第二个参数是写入的语句,其中\t,\n依旧是空格,换行等操作:
    在这里插入图片描述
    其中$outputstring字符串内容为:
    在这里插入图片描述
    操作完毕解除锁定,关闭文件:
    在这里插入图片描述

    运行并查看文件

    在这里插入图片描述

    完整代码

    processorder.php

    <?php 
    //create short variable names 
    $tireqty=$_POST['tireqty']; 
    $oilqty=$_POST['oilqty']; 
    $sparkqty=$_POST['sparkqty']; 
    $address=$_POST['address']; 
    $DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT']; 
    $date=date('H:i,jS F Y');
    define('TIREPRICE',100); 
    define('OILPRICE',10); 
    define('SPARKPRICE',4); 
    ?>
    <html> 
    <head> 
    <title>Bob's Auto Parts-Order Results</title> 
    </head> 
    <body> 
    <h1>Bob's Auto Parts</h1> 
    <h2>Order Results</h2> 
    <?php 
    echo"<p>Order processed at".date('H:i,jS F Y')."</p>"; 
    echo"<p>Your order is as follows:</p>"; 
    $totalqty=0; 
    $totalqty=$tireqty+$oilqty+$sparkqty; 
    echo"Items ordered:".$totalqty."<br/>"; 
    if($totalqty==0){ 
    echo"You did not order anything on the previous page!<br/>"; 
    }else{ 
        if($tireqty>0){ 
            echo$tireqty."tires<br/>"; 
        }if($oilqty>0){ 
            echo$oilqty."bottles of oil<br/>"; 
        }if($sparkqty>0){ 
            echo$sparkqty."spark plugs<br/>"; 
        }
    }
    $totalamount=0.00;  
    $totalamount=$tireqty*TIREPRICE +$oilqty*OILPRICE +$sparkqty*SPARKPRICE; 
    $totalamount=number_format($totalamount,2,'.',''); 
    echo"<p>Total of order is$".$totalamount."</p>"; 
    echo"<p>Address to ship to is".$address."</p>"; 
    $outputstring=$date."\t".$tireqty."tires\t".$oilqty."oil\t" 
    .$sparkqty."spark plugs\t\$".$totalamount 
    ."\t".$address."\n";
    
    
    //open file for appending 
    @$fp=fopen("$DOCUMENT_ROOT/../orders.txt",'ab');
    flock($fp,LOCK_EX); 
    if(!$fp){ 
        echo"<p><strong>Your order could not be processed at this time. 
        Please try again later.</strong></p></body></html>"; 
        exit; 
    }
    fwrite($fp,$outputstring,strlen($outputstring)); 
    flock($fp,LOCK_UN); 
    fclose($fp); 
    echo"<p>Order written.</p>"; 
    ?>
    </body>
    

    读出文件

    首先,新建立一个文件,名为vieworders.php,路径和processorder.php相同;
    依旧是先赋值:
    在这里插入图片描述
    打开文件并且上锁,并且注意这里的锁是LOCK_SH,即可以共享,并不是锁定不让其它进程操作,而是告诉其他进程我正在读取,其他进程可以共享读取这个文件:
    在这里插入图片描述
    feof(),遍历参数中的文件指针所指向的文件,当遍历到末尾时,返回true;
    fgets()、fgetss()和fgetcsv():可以每次读取参数一文件中一行数据,直到读到\n或者读取的字节数为998B结束
    在这里插入图片描述
    结束以后解除上锁:
    在这里插入图片描述

    运行并查看文件

    即刚刚写入orders.txt文件的内容
    在这里插入图片描述

    完整代码

    <?php 
    //create short variable name 
    $DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT']; 
    ?>
    <html> 
    <head> 
    <title>Bob's Auto Parts-Customer Orders</title> 
    </head> 
    <body> 
    <h1>Bob's Auto Parts</h1> 
    <h2>Customer Orders</h2> 
    <?php 
    @$fp=fopen("$DOCUMENT_ROOT/../orders.txt",'rb'); 
    flock($fp,LOCK_SH);
    if(!$fp){ 
        echo"<p><strong>No orders pending. Please try again later.</strong></p>"; 
        exit; 
    }
    while(!feof($fp)){ 
        $order=fgets($fp,999); 
        echo$order."<br/>"; 
    }
    flock($fp,LOCK_UN); 
    ?>
    </body>
    

    五、其它有关于文件操作的一些函数

    读取整个文件readfile("$DOCUMENT_ROOT/../orders.txt")
    读取一个字符fgetc($fp)
    读取任意长度fread($fp, length)
    查看文件是否存在(存在返回true)file_exists("$DOCUMENT_ROOT/../orders.txt")
    确定文件大小filesize("$DOCUMENT_ROOT/../orders.txt")
    删除一个文件unlink("$DOCUMENT_ROOT/../orders.txt")
    在文件中定位 ,rewind()函数可以将文件指针复位到文件的开始。ftell()函数可以以字节为单位报告文 件指针当前在文件中的位置。fseek()函数可以将文件指针fp从whence位置移动offset个字节:
    ftell($fp) fseek($fp,offset)
    文件锁定:flock($fp,lock)
    在这里插入图片描述

    六、更好的方式—数据库

    Q:为什么要使用数据库
    使用普通文件,你可能会遇到如下这些问题:
    ■当文件变大时,使用普通文件将会变得非常慢。
    ■在一个普通文件中查找特定的一个或者一组记录将会非常困难。
    ■处理并发访问可能会遇到问题。
    ■到目前为止,我们所看到的文件处理都是顺序的文件处理——也就是我们从文件开 始处一直读到文件的结束。如果我们希望在文件中间插入记录或者删除记录(随机访 问),这可能会比较困难——你将必须将整个文件读入到内存中,在内存中修改它,然后 再将整个文件写回去。如果这是一个很大的数据文件,这可能会带来巨大的开销。
    ■除了使用文件访问权限作为限制外,还没有一个简单的方法可以区分不同级别的数 据访问。
    数据库实例演练
    PHP与数据库基础知识

    展开全文
  • 一、文件系统与数据库系统的概念及其发展 1.文件系统  所谓的文件系统简单地说负责存取和管理文件信息的软件结构。例如电脑的硬盘C、D、E、F盘和可以动的存储设备等。文件系统是操作系统用于明确磁盘或分区上的...

    一、文件系统与数据库系统的概念及其发展 

    1.文件系统 
      所谓的文件系统简单地说负责存取和管理文件信息的软件结构。例如电脑的硬盘C、D、E、F盘和可以动的存储设备等。文件系统是操作系统用于明确磁盘或分区上的文件的方法和数据结构,即在磁盘上组织文件的方法。也指用于存储文件的磁盘或分区,或文件系统种类。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。 
      文件系统由三部分组成:与文件管理有关软件、被管理文件以及实施文件管理所需数据结构。从系统角度来看,文件系统是对文件存储器空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。

     2.数据库系统 
      数据库系统是由数据库及数据库管理软件组成的系统,它是为适应数据处理的需要而发展起来的一种较为理想的数据处理的核心机构。它是一个实际可运行的存储、维护和应用系统提供数据的软件系统,是存储介质、处理对象和管理系统的集合体。数据库系统的核心是数据库管理系统。 
    数据库系统一般由4个部分组成:数据库、硬件、软件、人员。

      其中数据库是指长期存储在计算机内的,有组织,可共享的数据的集合。硬件是指构成计算机系统的各种物理设备,包括存储所需的外部设备。软件包括操作系统、数据库管理系统及应用程序。人员包括系统分析员和数据库设计人员、应用程序员、最终用户、数据库管理员。

      数据库系统有大小之分,常见的大型数据库系统有SQL Server、Oracle、DB2等;中小型数据库系统有Foxpro、Access等。

    3.发展过程

      数据库发展阶段大致划分为如下几个阶段:人工管理阶段、文件系统阶段、数据库系统阶段、高级数据库阶段。以下主要介绍一下文件系统管理阶段和数据库管理阶段。文件系统阶段中操作系统的出现标志着数据管理步入一个新的时期。在文件系统阶段,数据以文件为单位存储在外存,且由操作系统统一管理。操作系统为用户使用文件提供了友好界面。文件的逻辑结构与物理结构脱钩,程序和数据分离,使数据与程序有了一定的独立性。用户的程序与数据可分别存放在外存储器上,各个应用程序可以共享一组数据,实现了以文件为单位的数据共享。

    在数据库系统阶段,人们对数据管理技术提出了更高的要求:希望面向企业或部门,以数据为中心组织数据,减少数据的冗余,提供更高的数据共享能力,同时要求程序和数据具有较高的独立性,当数据的逻辑结构改变时,不涉及数据的物理结构,也不影响应用程序,以降低应用程序研制与维护的费用。数据库技术正是在这样一个应用需求的基础上发展起来的。

    通过上面的内容可以看出数据库系统是在文件系统的基础上发展而来的。

    二、文件系统存储与数据库系统存储的区别与联系

      文件系统与数据库系统的本质区别在于:

      文件系统把数据组织成相互独立的数据文件,实现了记录内的结构性,但整体无结构;而数据库系统实现整体数据的结构化。

    在文件系统中,数据冗余度大,浪费存储空间,容易造成数据的不一致,但是在数据库系统中,数据是面向整个系统,数据可以被多个用户、多个应用共享使用,减少了数据冗余。文件系统中的文件是为某一特定应用服务的,当要修改数据的逻辑结构时,必须修改应用程序,修改文件结构的定义,数据和程序之间缺乏独立性,数据库系统中,通过DBMS的两级映象实现了数据的物理独立性和逻辑独立性,把数据的定义从程序中分离出去,减少了应用程序的维护和修改。

      文件系统和数据库系统均可以长期保存数据,由数据管理软件管理数据,数据库系统是在文件系统基础上发展而来。

    数据库系统主要管理数据库的存储、事务以及对数据库的操作。文件系统是操作系统管理文件和存储空间的子系统,主要是分配文件所占的簇、盘块或者建立FAT、管理空间空间等。一般来说数据库系统会调用文件系统来管理自己的数据文件,但也有些数据库系统能够自己管理数据文件,甚至在裸设备上。文件系统是操作系统必须的,而数据库系统只是数据库管理和应用所必需的。

    三、总结

    综上所述,文件系统和数据库系统之间既有区别又有联系。

    其区别在于:

      (1)文件系统用文件将数据长期保存在外存上,数据库系统用数据库统一存储数据。

      (2)文件系统中的程序和数据有一定的联系,数据库系统中的程序和数据分离。

      (3)文件系统用操作系统中的存取方法对数据进行管理,数据库系统用DBMS统一管理和控制数据。

      (4)文件系统实现以文件为单位的数据共享,数据库系统实现以记录和字段为单位的数据共享。

    其联系在于:

      (1)均为数据组织的管理技术。

      (2)均由数据管理软件管理数据,程序与数据之间用存取方法进行转换。

      (3)数据库系统是在文件系统的基础上发展而来的。

    总之,文件系统存储和数据库系统存储各有利弊,两种存储方式都广泛的应用于现实社会中的各个领域。

     

     

    展开全文
  • 爬虫数据存储数据库和MySQL

    千次阅读 2019-10-31 15:56:46
    爬虫数据存储数据库 一、什么是数据库? 数据库是一个以某种有组织的方式存储的数据集合。简单来说,我们可以将数据库想象为一个文件柜,文件柜里面有很多文件,这些文件我们称之为表。 举一个实际例子:比如说...
  • 文章背景:相信大部分刚接触上面三个概念的同学,都多多少少会有些迷惑,现在我就给大家简单...数据库与数据仓库的区别与联系数据库与数据仓库基础概念:数据库:传统的关系型数据库的主要应用,主要是基本的、日常的
  • 一、四大非关系型数据库:键值对存储(key-value)、文档存储(document store)、基于列的数据库、图形数据库 二、关系型数据库 转载于:https://www.cnblogs.com/fllowerqq/p/8984528.html...
  •  数据库系统用数据库统一存储数据。 (2) 文件系统中的程序和数据有一定的联系,  数据库系统中的程序和数据分离。 (3) 文件系统用操作系统中的存取方法对数据进行管理,  数据库系统用DBMS统一管理和控制数据...
  • 本文主要从下面两类关系来叙述上面三者的关系:数据库(DB)和数据仓库(DW)的区别与联系操作数据存储(ODS)和数据仓库(DW)的区别与联系数据库与数据仓库的区别与联系数据库与数据仓库基础概念:数据库:传统的...
  • 用户登录的密码用MD5算法进行加密,然后当用户输入用户名和密码时,先去数据库查找用户名是否存在,若存在,就将加密密码与数据库中密码进行比对,正确则显示输入正确,错误则显示错误,用JAVA代码实现。...
  • 前段页面输入密码存储数据库中加密密码作比较,进行验证,验证通过,就进入用户页面,验证未通过,就进入登录界面 原问题代码 public BaseReturnInfo androidLogin(@RequestParam String phoneNumber...
  • 数据导入到数据库中,并使用SQLserver内置函数把密码加密后,那么我的登录功能就要修改,用户输入的肯定是加密前的密码,那么如何把用户加密前的密码与数据库中加密后的密码做比较,来让用户正确登录呢?...
  • MySQL数据库存储过程讲解实例

    万次阅读 多人点赞 2018-06-03 00:48:17
    SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储数据库中用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。...
  • 将爬取的数据存储数据库

    千次阅读 2018-07-20 23:28:06
    之前都是将数据存到了文档或者excel(排版很不好,稍后研究一下),今天尝试一下对数据库的操作…… 先上代码吧: class Mysql_Exe(): def _getconn(self): try: self.conn=pymysql.connect(host='...
  • 数据库存储过程

    万次阅读 2017-12-02 19:07:18
    SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储数据库中用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。...
  • 用户注册时就对用户密码进行MD5加密,这样用户中存储密码就是加密的信息,就算管理员也不能看到用户密码用户在登录时输入账号和密码,在后台把用户密码惊醒MD5摘要之后和数据库密码就行比对,...
  • 从文本文件读取数据存储数据库

    千次阅读 2014-06-06 16:42:56
    package file; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement;...impor
  • 直接上代码,解释在代码以及文末; charset=UTF-8" //这是获取userid需要首先写入到方法 //调用db.java的方法 pageEncoding="UTF-8"%> *" import= "java.util.*"%>
  • 多维数据库数据存储

    千次阅读 2011-08-27 16:45:53
    在多维数据库中二维数据很容易理解,维数扩展到三维或更高的维度时,多维数据库MDDB就成了一种“超立方”体的结构。在MDDB,其数据存储是由许多类似于数组的对象来完成 。 对象包含了经过高度压缩的索引和...
  • 数据库存储过程简单介绍

    千次阅读 2019-03-05 15:37:35
    存储过程就是一条或多条SQL语句的集合 当对数据库进行一系列的操作时 存储过程就可以将这些复杂的操作封装成一个代码块 以便重复使用 大大减少了数据库开发人员的工作量 创建存储过程 创建存储过程的基本语法 CREATE...

空空如也

1 2 3 4 5 ... 20
收藏数 1,407,568
精华内容 563,027
关键字:

数据存储与数据库