码迷,mamicode.com
首页 > 数据库 > 详细

oracle_事务与undo块

时间:2015-01-17 12:40:28      阅读:391      评论:0      收藏:0      [点我收藏+]

标签:


1.事务(transaction)

1.1事务的概念
    事务是若干操作的集合,集合中的操作看作程一个整体,要么都完成,要么都取消。
1.2事务的属性
    Atomicity(原子性) 事务是一个整体,一起完成,一起取消。
    Consistency(一致性) 事务将数据从一种一致状态转变为下一种一致状态。(指的是修改前与修改后吗?留疑)
    Isolation(隔离性) 一个事物的影响在该事物提交前对其他事务都不可见。(由undo表空间完成)
    Durability(永久性) 事务一旦提交,结果是永久的。(通过重做日志机制,达到的效果。而不是直接写入磁盘。)

1.3事务的控制操作
    和sql server不同,Oracle没有专门的开始事务控制语句。
    在修改数据语句之前,Oracle会自动添加一个隐式的开始事务语句。
1.3.1事务操作语句
    commit  --提交语句。commit会结束你的事务,并把事务做的修改永久化。
    rollback  --回滚语句。rollback会结束事务,并撤销未提交的事务。
    savepoint <savepoint_name>  --容许在事务中做一个保存标记点。(一个事务中可以有多个savepoint)
    rollback to <savepoint_name>  --与上面savepoint一起使用,可以rollback到这个点。
    
    实验:
    SQL> select * from scott.emp where empno in(7369,7499,7521);
         EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
          7369 SMITH      CLERK           7902 17-12月-80           1000                    20
          7499 ALLEN      SALESMAN        7698 20-2月 -81            200        300         30
          7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
    

    SQL> update scott.emp set sal=800 where empno=7369;
    已更新 1 行。
    SQL> update scott.emp set sal=500 where empno=7499;
    已更新 1 行。
    SQL> savepoint t1;
    保存点已创建。
    SQL> update scott.emp set sal=1000 where empno=7521;
    已更新 1 行。
    SQL> rollback to t1;
    回退已完成。


    SQL> select * from scott.emp where empno in(7369,7499,7521);
         EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
          7369 SMITH      CLERK           7902 17-12月-80            800                    20
        7499 ALLEN      SALESMAN        7698 20-2月 -81            500        300         30
        7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30

    --可以看到前两个update已修改,只是rollback到了savepoint。

    SQL> rollback;
    回退已完成。

    SQL> select * from scott.emp where empno in(7369,7499,7521);
    EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
          7369 SMITH      CLERK           7902 17-12月-80           1000                    20
          7499 ALLEN      SALESMAN        7698 20-2月 -81            200        300         30
          7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30

    --这下全部撤销。
    --小总结:一个事物中,savepoint可以多个;rollback可以多次撤销。


1.4事务与undo表空间

    Oracle中undo的作用主要有两个:第一是回滚事务,第二是产生一致性读。
    
    XID=usn#:slot#:wrap#           --transaction identifiers(XID--事务ID)
        usn    rollback segment number 回滚段序号 
        slot    transaction table slot number 事务表槽号
        wrap    sequence number or wrap# 被覆盖次数
    
    UBA=DBA:seq#:rec#:              --undo block address(undo块地址) 
        DBA    data block address of the undo block 回滚块地址     
        seq#    the sequence number of the block 覆盖次数
        rec#    the record number within the block 块中的第几行

    ITL       --Interested Transaction List 事务槽


1.4.1一个事务的操作流程。
    我们可以通过下图,系统了解下事务的执行流程。

技术分享

    1.一个事务先在shared Pool解析。(以硬解析为例)
    2.在buffer cache中寻找事务所需要的块。
    3.数据块读入buffer cahce。
    4.产生重做日志信息,记日志。
    5.为事务建立undo段。
    6.事务修改数据块的详细步骤。
        6.1事务开始,必须首先在data block中分配ITL(事务槽),ITL中记录了事务ID(XID),XID由三部分内容组成:
            XIDUSN(回滚段号),XIDSLOT(回滚段槽号),XIDSQN(覆盖次数)。
        6.2分配对应的undo块,用于保存修改之前data block的数据。data block的ITL和undo block的ITL都记录着相同的UBA                      block address) 
        6.3在Undo segment header中的事务表中,记录所有回滚块上的事务信息,每个事务都会占据了一个回滚槽。
            XID指向data block。 
            UBA指向事务回滚信息的开始位置。undo块存储是一个链表结构,只要找到最先开始回滚的块,就能依次回滚整个事务。

    小结undo的内容:
    1.为事务建立undo段。
    2.在数据块的ITL中存储XID,UBA.
    3.在undo表头中存储相对应的数据 块的XID,UBA.
    4.建立undo块,存储数据块镜像。数据块中的UBA指向undo块。同样有xid,uba。






1.4.2.1.实验说明。

        第6步,dump出了undo段头信息。
        第8步,dump出来data block中ITL的信息。
        第10步,dump出了undo block中信息。


        证明--下面一张根据这次事务所作的图,结合图理解

技术分享

           

            undo 段表中记录着每一个事务的XID和UBA                   ---实验中用红色字体标注出XID,UBA
            data block中ITL的XID指向undo段头
            undo 段头中的UBA指向undo block


            
1.4.3实验开始

    1.触发一个事务
    SQL> update scott.emp set sal=800 where empno=7369;
    已更新 1 行。
    
    SQL> update scott.emp set sal=800 where empno=7369;
    已更新 1 行。

    SQL> update scott.emp set sal=800 where empno=7369;
    已更新 1 行。



    2.查询事务的XID,回滚段序号,事务表序号,覆盖次数,undo块,undo文件号。
    SQL> select xid,xidusn,xidslot,xidsqn,ubablk,ubafil from v$transaction;
    XID                  XIDUSN    XIDSLOT     XIDSQN     UBABLK     UBAFIL
    ---------------- ---------- ---------- ---------- ---------- ----------
    04001300F3070000          4         19       2035      24247          5




    3.通过回滚段序号,可以查到对应的回滚段。(XIDUSN=4,所以该事物的回滚段是_SYSSMU4_3587866380$)
    SQL> select  * from v$rollname;
       USN NAME                               CON_ID
    ---------- ------------------------------ ----------
         0 SYSTEM                                  0
         1 _SYSSMU1_2129601957$                    0
         2 _SYSSMU2_4159822658$                    0
         3 _SYSSMU3_2248346778$                    0
         4 _SYSSMU4_3587866380$                    0
         5 _SYSSMU5_2367258232$                    0
         6 _SYSSMU6_3229781354$                    0
         7 _SYSSMU7_2293707892$                    0
         8 _SYSSMU8_1104184495$                    0
         9 _SYSSMU9_376956797$                     0
        10 _SYSSMU10_2767132874$                   0
    已选择 11 行。



    4.dump出该undo段块头。

    SQL> alter system dump undo header ‘_SYSSMU4_3587866380$‘;
    系统已更改。


    5.跟踪着转储文件的位置。
    SQL> select * from v$diag_info where name=‘Default Trace File‘;
       INST_ID NAME                      VALUE                                                              CON_ID
    ---------- ------------------------- ---------------------------------------------------------------------- ----------
             1    Default Trace File        F:APPADMINISTRATORdiag dbmsyzhyzh raceyzh_ora_1604.trc              0
    


    6.详细看undo段块头的信息,(篇幅很长。)    (图rollback segment header block,结合图理解)

技术分享

    *** 2014-12-18 20:14:33.420
    ********************************************************************************
    Undo Segment:  _SYSSMU4_3587866380$ (4)
    ********************************************************************************



      Extent Control Header
      -----------------------------------------------------------------
      Extent Header:: spare1: 0      spare2: 0      #extents: 5      #blocks: 655   
                  last map  0x00000000  #maps: 0      offset: 4080  
          Highwater::  0x01405eb7  ext#: 4      blk#: 55     ext size: 256   
      #blocks in seg. hdr‘s freelists: 0     
      #blocks below: 0     
      mapblk  0x00000000  offset: 4     
                   Unlocked
         Map Header:: next  0x00000000  #extents: 5    obj#: 0      flag: 0x40000000

    ********************************************************************************
    先一部分一部分来看。
    #extents: 5      --这个undo段共有5个区。
    #blocks: 655     --有655可用块。
    ext#: 4          --这个事务发生在第五个区上。(从0开始)
    blk#: 55         --这个事务发生在第55个快上。
    ext size: 256    --第5个区还有256个块可用。
    Highwater::  0x01405eb7   --段头的下一块。
    ********************************************************************************





      Extent Map
      -----------------------------------------------------------------
       0x014000b1  length: 7     
       0x014000b8  length: 8     
       0x01402380  length: 128   
       0x01405500  length: 256   
       0x01405e80  length: 256     
    ********************************************************************************
    代表各个区的各有多少undo块。
    ********************************************************************************




     Retention Table 
      -----------------------------------------------------------
     Extent Number:0  Commit Time: 1418211204
     Extent Number:1  Commit Time: 1418211204
     Extent Number:2  Commit Time: 1418824836
     Extent Number:3  Commit Time: 1418896851
     Extent Number:4  Commit Time: 1418896851
    ********************************************************************************
    区提交的时间,以秒为单位。
    ********************************************************************************






      TRN CTL:: seq: 0x00e4 chd: 0x000f ctl: 0x0014 inc: 0x00000000 nfb: 0x0000
                mgc: 0xb000 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
                uba: 0x01405eb7.00e4.33 scn: 0x0000.00299627
    ******************************************************************************************************************************
    重点看这里!  (十六进制转十进制)
    seq: 0x00e4      被覆盖228次。
    chd: 0x000f    事务表的链头,这里是15.
    ctl: 0x0014    事务表的链尾,这里是20. 
    nfb: 0x0000     表示UNDO块在空闲池的空闲块数。    
    uba: 0x01405eb7.00e4.33          (记住这个。)       
        分为三部分:
        0x01405eb7      代表undo块地址。
        00e4         代表被覆盖次数.          --即UNDO块被覆盖了228次    (这里和seq是一样的)
        33        代表在undo块的第几行记录。  --undo块的51条记录

    ******************************************************************************************************************************





    Version: 0x01
      FREE BLOCK POOL::
        uba: 0x00000000.00e4.32 ext: 0x4  spc: 0x5fa   
        uba: 0x00000000.00e4.28 ext: 0x4  spc: 0xf62   
        uba: 0x00000000.00e4.12 ext: 0x4  spc: 0xe4e   
        uba: 0x00000000.00d1.01 ext: 0x5  spc: 0x1f9c  
        uba: 0x00000000.00d0.16 ext: 0x4  spc: 0x1786   
    ***********************************************************************************************************************
    undo块的空闲池。
    uba: 0x00000000.00e4.32    块地址为0,说明UNDO块不是空闲的,即0x00000000
    ext: 0x4    undo块在哪个区。这里是在第四个区。
    spc: 0x5fa   undo块中有多少空闲空间,单位字节。
    ***********************************************************************************************************************




    TRN TBL::
 
      index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
      ------------------------------------------------------------------------------------------------
       0x00    9    0x00  0x07f6  0x0006  0x0000.0029e758  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x01    9    0x00  0x07f2  0x0017  0x0000.0029e72e  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x02    9    0x00  0x07f4  0x0020  0x0000.0029e642  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x03    9    0x00  0x07f3  0x0012  0x0000.0029e5f1  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903967
       0x04    9    0x00  0x07f3  0x0003  0x0000.0029e5ce  0x00000000   0x0000.000.00000000  0x00000000   0x00000000  1418903948
       0x05    9    0x00  0x07f4  0x000e  0x0000.0029e6a1  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x06    9    0x00  0x07f5  0x001d  0x0000.0029e75d  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x07    9    0x00  0x07f5  0x0014  0x0000.0029e9a5  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418904001
       0x08    9    0x00  0x07f5  0x0021  0x0000.0029e6bb  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x09    9    0x00  0x07f6  0x000b  0x0000.0029e6d3  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x0a    9    0x00  0x06e7  0x0016  0x0000.0029e66a  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x0b    9    0x00  0x07f3  0x001f  0x0000.0029e6e9  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x0c    9    0x00  0x07f4  0x000a  0x0000.0029e665  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x0d    9    0x00  0x07f4  0x001b  0x0000.00299635  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418898808
       0x0e    9    0x00  0x07f2  0x0008  0x0000.0029e6ad  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x0f    9    0x00  0x07f5  0x000d  0x0000.0029962c  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418898808
       0x10    9    0x00  0x07f5  0x0007  0x0000.0029e8c5  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903983
       0x11    9    0x00  0x07ec  0x0010  0x0000.0029e879  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903982
      0x12    9    0x00  0x07e8  0x0018  0x0000.0029e60b  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903971
       0x13   10    0x80  0x07f3  0x0004  0x0000.0029e9b8  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  0
       0x14    9    0x00  0x07f3  0xffff  0x0000.0029e9ad  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418904001
       0x15    9    0x00  0x07f3  0x0001  0x0000.0029e71d  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x16    9    0x00  0x07f1  0x0019  0x0000.0029e674  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x17    9    0x00  0x07f7  0x001c  0x0000.0029e734  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x18    9    0x00  0x07f5  0x0002  0x0000.0029e62e  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x19    9    0x00  0x07ef  0x0005  0x0000.0029e68c  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x1a    9    0x00  0x07f1  0x0015  0x0000.0029e705  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x1b    9    0x00  0x07f2  0x0004  0x0000.0029967f  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418898903
       0x1c    9    0x00  0x07ef  0x0000  0x0000.0029e748  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x1d    9    0x00  0x07f3  0x0011  0x0000.0029e798  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903977
       0x1e    9    0x00  0x07f5  0x000c  0x0000.0029e663  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x1f    9    0x00  0x07f6  0x001a  0x0000.0029e6ef  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x20    9    0x00  0x07f2  0x001e  0x0000.0029e656  0x01405eb6   0x0000.000.00000000  0x00000001   0x00000000  1418903973
       0x21    9    0x00  0x07f3  0x0009  0x0000.0029e6cc  0x01405eb7   0x0000.000.00000000  0x00000001   0x00000000  1418903973
    ***********************************************************************************************************************
    index 表示事务表中槽号,从0x00开始到0x21结束,11g的版本有34个槽。
    uel 表示所在undo段序号。对应xid中的usn
    wrap# 表示被覆盖次数。
    ---这三者结合起来即是XID。

    state 表示事务状态:9代表事务不活动,10代表事务正在活动。
    cflags 表示正在使用穿上事务槽的事务的状态:0x00表示非活动事务、0x80表示活动事务、0x10表示死事务。
    scn   表示务事启动、提交、回滚的SCN.
    dba   表示uba:第一部分的undo块地址。
    nub   表示当前事务所用到的UNDO块的个数。
    cmt   表示最接近当前的提交时间戳,0表示事务正在活动。
    ***********************************************************************************************************************






    7.使用dbms_rowid包得出该事物修改的数据块。
    SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid),empno from emp where empno=7369;
    DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)      EMPNO
    ------------------------------------ ------------------------------------ ----------
                                       6                                  323       7369


    8.dump出数据块。
    SQL> alter system dump datafile 6 block 323;
    系统已更改。
    SQL> select * from v$diag_info where name=‘Default Trace File‘;
       INST_ID NAME                      VALUE                                                              CON_ID
    ---------- ------------------------- ---------------------------------------------------------------------- ----------
             1 Default Trace File        F:APPADMINISTRATORdiag dbmsyzhyzh raceyzh_ora_1604.trc              0




    9.详细看看数据块头信息。(图data block header:transaction layer,结合图理解)

技术分享

    ********************************************************************************
    以下是该事物需要到数据块中的ITL一部分。
    ********************************************************************************


    *** 2014-12-18 22:27:39.268
    Block header dump:  0x01800143
     Object id on Block? Y
     seg/obj: 0x16d78  csc: 0x00.2a0b11  itc: 3  flg: E  typ: 1 - DATA
         brn: 0  bdba: 0x1800140 ver: 0x01 opc: 0
         inc: 0  exflg: 0
    ***********************************************************************************************************************
    seg/obj: 0x16d78           --object_id号。十六转十,可以在dba_objects上查到。
    csc: 0x00.2a0b11    --cleanSCN。清除时的SCN(覆盖时的SCN)
    itc: 3            --该块ITL的数量。Oracle的每个数据块中都有一个或者多个事务槽,每一个对数据块的并发访问
                     事务都会占用一个事务槽。 
    flg: E            --指ASSM(automatic segment space management自动段空间管理(段空间有两种方法管理))。
              如果是O表示用的是free list。
    typ: 1 - DATA        --类型1表示数据,类型2表示索引 
    ***********************************************************************************************************************

 






     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0002.00e.000008e9  0x014003e2.0105.01  C---    0  scn 0x0000.0028cfa3
    0x02   0x0005.00a.00000943  0x014000c3.0160.0b  C---    0  scn 0x0000.0028dced
    0x03   0x0004.013.000007f3  0x01405eb7.00e4.35  ----    3  fsc 0x0001.00000000

    ********************************************************************************
    Itl            -- ITL事务槽号的流水编号
    Xid            -- transac[X]tion identified(事务ID),在回滚段事务表中有一条记录和这个事务对应。           
    Uba            --undo block address记录了最近一次的该记录的前镜像(修改前的值,对应数据块的UBA)
    Flag            --C是提交,U是快速提交,---是未提交
    Lck            --锁住了几行数据,即是有几个行锁(行锁)
    ********************************************************************************






    10.从第二步,可以知道undo块的位置。(ubablk,ubafil  ---v$transaction)
    dump出undo块头。(图为undor block结构,结合图理解)

    技术分享


    UNDO BLK:
  
     xid: 0x0004.013.000007f3  seq: 0xe4  cnt: 0x35  irb: 0x35  icl: 0x0   flg: 0x0000
    ********************************************************************************
    主要看上面这个字段:
    xid: 0x0004.013.000007f3    事务ID,对应数据块中ITL的XID。
    seq: 0xe4 块序号  0xe4是228.
    cnt: 0x35 块中回滚记录次数
    irb: 0x35 index of first to consider in case of a transaction rollback
    icl: 0x0
    ********************************************************************************
 




     Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
    ---------------------------------------------------------------------------
    0x01 0x1f3c     0x02 0x1ed4     0x03 0x1e6c     0x04 0x1e04     0x05 0x1d8c     
    0x06 0x1d24     0x07 0x1cbc     0x08 0x1c10     0x09 0x1b64     0x0a 0x1ab8     
    0x0b 0x1a50     0x0c 0x19e8     0x0d 0x1980     0x0e 0x18d4     0x0f 0x1828     
    0x10 0x17c0     0x11 0x1758     0x12 0x16f0     0x13 0x1644     0x14 0x15dc     
    0x15 0x1530     0x16 0x14c8     0x17 0x141c     0x18 0x13a4     0x19 0x131c     
    0x1a 0x12c4     0x1b 0x1218     0x1c 0x116c     0x1d 0x1104     0x1e 0x1058     
    0x1f 0x0fac     0x20 0x0ef4     0x21 0x0e94     0x22 0x0e44     0x23 0x0df4     
    0x24 0x0d14     0x25 0x0cc4     0x26 0x0be4     0x27 0x0b60     0x28 0x0b04     
    0x29 0x0ab4     0x2a 0x0a54     0x2b 0x09a0     0x2c 0x0938     0x2d 0x08e0     
    0x2e 0x0880     0x2f 0x0830     0x30 0x074c     0x31 0x06c8     0x32 0x0670     
    0x33 0x05d8     0x34 0x0584     0x35 0x052c     
 
    *-----------------------------   
    * Rec #0x34  slt: 0x13  objn: 93560(0x00016d78)  objd: 93560  tblspc: 4(0x00000004)
    ***********************************
    Rec #0x34  --undo块中的第52行记录
    slt: 0x13  --undo块中的槽号。
    ***********************************

    *       Layer:  11 (Row)   opc: 1   rci 0x33   
    Undo type:  Regular undo   Last buffer split:  No 
    Temp Object:  No 
    Tablespace Undo:  No 
    rdba: 0x00000000
    *-----------------------------
    KDO undo record:
    KTB Redo 
    op: 0x02  ver: 0x01  
    compat bit: 4 (post-11) padding: 0
    op: C  uba: 0x01405eb7.00e4.33
    KDO Op code: URP row dependencies Disabled
      xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x01800143  hdba: 0x01800142
    itli: 3  ispac: 0  maxfr: 4858
    tabn: 0 slot: 1(0x1) flag: 0x2c lock: 0 ckix: 0
    ncol: 8 nnew: 1 size: 0
    Vector content: 
    col  5: [ 2]  c2 03
    ********************************************
    col  5: [ 2]  c2 03   --表示具体的undo数据
    ********************************************

oracle_事务与undo块

标签:

原文地址:http://www.cnblogs.com/yzhl/p/4226897.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!