談談undo表空間


Oracle比其他數據庫牛逼的地方好幾個,其中一個很重要的就是undo表空間的引入(當然,鎖也是很牛逼的一個東西)

1.oracle段的類型:

SQL> select segment_type from dba_segments t group by t.segment_type;

SEGMENT_TYPE
------------------
LOBINDEX
INDEX PARTITION
TABLE PARTITION
NESTED TABLE
ROLLBACK
LOB PARTITION
LOBSEGMENT
INDEX
TABLE
CLUSTER
TYPE2 UNDO

在dba_tablespace中.表空間的類型分為:undo,temporary,permanent

 

2.查看undo表空間創建之后創建的段

select * from dba_segments where tablespace_name = 'UNDOTBS1';

每一個undo段至少要有2個extent

也可以查看

select * from dba_rollback_segs

在status一欄有顯示從數據庫啟動用的有10個undo段,如果存在多個undo表空間,那么從status=online的可以查看當前在用的回滾段.
個人認為9i的最大貢獻就是,開始undo可以自動管理

 

3.每個回滾段最多有幾個事務數?

在9i以前通過參數transactions_per_rollback_segment(默認是5個),現在已經失效,從10g開始默認一個回滾段上只有一個事務,如果回滾段不夠的話,那么就自己創建undo段,直到undo表空間用完.這個時候,回滾段上的事務才開始有多個.


4.最牛逼的一致性讀

一致性讀(Consistent Get)是Oracle一個非常優秀的特性.(當然它也是產生ora-1555錯誤的主要原因)
在標准SQL中,為了防止並發事務中產生臟讀,就需要通過加鎖來控制.這樣就會帶來死鎖、阻塞的問題,即時是粒度最小的行級鎖,也無法避免這些問題.
為了解決這一矛盾,Oracle充分利用的回歸段,通過會滾段進行一致性讀取,即避免了臟讀,又大大減少了系統的阻塞、死鎖問題.
Oracle是如何實現一致性讀的:
當Oracle更新數據塊(Data Block Oracle中最小的存儲單位)時,會在兩個地方記錄下這一更新動作.一個是在Redo Segment,.一個是回滾段UNDO Segment.並在數據塊頭部標示出來是否有修改數據.一個語句在讀取數據快時,如果發現這個數據塊是在它讀取的過程中被修改的(即開始執行讀操作時並沒有被修改),就不直接從數據塊上讀取數據,而是從相應的回滾段條目中讀取數據.這就保證了最終結果應該是讀操作開始時的那一時刻的快照(snapshot),而不會受到讀期間其他事務的影響.這就是Oracle的一致性讀,也可以叫做多版本(Multi-Versioning).

 

5.ORACLE的據庫事務隔離級別

事務隔離級別:一個事務對數據庫的修改與並行的另一個事務的隔離程度。
兩個並發事務同時訪問數據庫表相同的行時,可能存在以下三個問題:
(1)幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,恰好滿足T1的where條件。然后T1使用相同的條件再次查詢,結果集中可以看到T2插入的記錄,這條新紀錄就是幻想。
(2)不可重復讀取:事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,然后T1再次查詢,發現與第一次讀取的記錄不同,這稱為不可重復讀。
(3)臟讀:事務T1更新了一行記錄,還未提交所做的修改,這個T2讀取了更新后的數據,然后T1執行回滾操作,取消剛才的修改,所以T2所讀取的行就無效,也就是臟數據。
為了處理這些問題,SQL標准定義了以下幾種事務隔離級別

SET TRANSACTION ISOLATION LEVEL
[READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

 Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。Oracle不支持臟讀。



6.Oracle是怎樣實現一致性讀的,我們可以通過以下實驗來查看

(1)建一個測試的表

SQL> create tablespace test datafile '/u01/app/oracle/oradata/pmisdb/test.dbf' size 20M;
Tablespace created.                                 
SQL> create table tt (id int,name varchar2(10)) tablespace test;
Table created.
SQL> 
SQL> insert into tt values(1,'a++');
1 row created.
SQL> insert into tt values(2,'b');
1 row created.
SQL> insert into tt values(3,'c');
1 row created.
SQL> commit;
Commit complete.
SQL> 
SQL> select * from tt;

        ID NAME
---------- ----------
         1 a++
         2 b
         3 c

SQL> 

(2).打開一個session A ,對改表進行update操作


session A >update tt set name='a' where id=1;

1 row updated.
session A >select * from tt;

        ID NAME
---------- ----------
         1 a
         2 b
         3 c
 
        

(3)打開一個session B ,進行查詢..因為有一致性讀的特性,所以在session B中,在A沒有提交前,B是看不到A修改的數據的.

session B >select * from tt;

        ID NAME
---------- ----------
         1 a++
         2 b
         3 c

session B >

(4)可以根據rowid以及oracle提供的dbms_rowid包來查看該條記錄所在的數據文件和數據塊

session A >select id,name,rowid from tt;

        ID NAME       ROWID
---------- ---------- ------------------
         1 a          AAARFuAAIAAAAAQAAA
         2 b          AAARFuAAIAAAAAQAAB
         3 c          AAARFuAAIAAAAAQAAC


SQL> select dbms_rowid.rowid_relative_fno('AAARFuAAIAAAAAQAAA') as file#,
  2         dbms_rowid.rowid_block_number('AAARFuAAIAAAAAQAAA') as block#
  3    from dual;

     FILE#     BLOCK#
---------- ----------
         8         16

(5)根據查詢到的文件號和塊號進行dump,注意這個地方dump的其實是內存里面的數據,如果需要dump磁盤上的數據文件,那么把8改成具體的路徑就可以了,因為oracle寫是異步的,這個時候磁盤的數據文件並不一定已經有這個信息了.

session A >alter system dump datafile 8 block 16;

System altered.

session A >SELECT d.VALUE || '/' || LOWER(RTRIM(i.INSTANCE, CHR(0))) || '_ora_' ||
  2         p.spid || '.trc' trace_file_name
  3    FROM (SELECT p.spid
  4            FROM v$mystat m, v$session s, v$process p
  5           WHERE m.statistic# = 1
  6             AND s.SID = m.SID
  7             AND p.addr = s.paddr) p,
  8         (SELECT t.INSTANCE
  9            FROM v$thread t, v$parameter v
 10           WHERE v.NAME = 'thread'
 11             AND (v.VALUE = 0 OR t.thread# = TO_NUMBER(v.VALUE))) i,
 12         (SELECT VALUE FROM v$parameter WHERE NAME = 'user_dump_dest') d;

TRACE_FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oracle/admin/pmisdb/udump/pmisdb_ora_3827.trc

(6)打開trace文件,進行觀察,分別截取開頭和有關事務的內容:

[root@pmiscs ~]# more /u01/app/oracle/admin/pmisdb/udump/pmisdb_ora_3790.trc
Dump file /u01/app/oracle/admin/pmisdb/udump/pmisdb_ora_3790.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      pmiscs
Release:        2.6.18-92.el5
Version:        #1 SMP Tue Apr 29 13:16:12 EDT 2008
Machine:        i686
Instance name: pmisdb
Redo thread mounted by this instance: 1
Oracle process number: 13
Unix process pid: 3790, image: oracle@pmiscs (TNS V1-V3)

*** ACTION NAME:() 2012-09-25 13:19:01.211
*** MODULE NAME:(sqlplus@pmiscs (TNS V1-V3)) 2012-09-25 13:19:01.211
*** SERVICE NAME:() 2012-09-25 13:19:01.211
*** SESSION ID:(544.3) 2012-09-25 13:19:01.211
Successfully allocated 2 recovery slaves
Using 543 overflow buffers per recovery slave
Thread 1 checkpoint: logseq 613, block 2, scn 18284996
  cache-low rba: logseq 613, block 449
    on-disk rba: logseq 613, block 508, scn 18285712
  change track rba: logseq 613, block 507, scn 18285711
  start recovery at logseq 613, block 449, scn 0
----- Redo read statistics for thread 1 -----
Read rate (ASYNC): 29Kb in 0.19s => 0.15 Mb/sec
Total physical reads: 4096Kb
Longest record: 2Kb, moves: 0/11 (0%)
Longest LWN: 6Kb, moves: 0/47 (0%), moved: 0Mb
Last redo scn: 0x0000.0117048f (18285711)
----------------------------------------------
----- Recovery Hash Table Statistics ---------
Hash table buckets = 32768
Longest hash chain = 1
Average hash chain = 9/9 = 1.0
Max compares per lookup = 1
Avg compares per lookup = 12/21 = 0.6
----------------------------------------------
*** 2012-09-25 13:19:01.442
KCRA: start recovery claims for 9 data blocks
*** 2012-09-25 13:19:01.499
KCRA: blocks processed = 9/9, claimed = 9, eliminated = 0
*** 2012-09-25 13:19:01.499
Recovery of Online Redo Log: Thread 1 Group 6 Seq 613 Reading mem 0
----- Recovery Hash Table Statistics ---------
Hash table buckets = 32768
Longest hash chain = 1
Average hash chain = 9/9 = 1.0
Max compares per lookup = 1
Avg compares per lookup = 21/21 = 1.0
----------------------------------------------
kwqmnich: current time::  5: 19:  6
kwqmnich: instance no 0 check_only flag 1 
kwqmnich: initialized job cache structure 
*** 2012-09-25 13:21:45.194
Start dump data blocks tsn: 10 file#: 8 minblk 16 maxblk 16
buffer tsn: 10 rdba: 0x02000010 (8/16)
scn: 0x0000.01175499 seq: 0x01 flg: 0x00 tail: 0x54990601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0DCC2400 to 0x0DCC4400

...

Block header dump:  0x02000010
 Object id on Block? Y
 seg/obj: 0x1116e  csc: 0x00.1175499  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x2000009 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0004.005.00000c41  0x00800c4a.0692.13  ----    1  fsc 0x0001.00000000
0x02   0x0003.01b.00000cfe  0x008006d1.072a.04  C---    0  scn 0x0000.01151109
 
data_block_dump,data header at 0xdcc2464
===============
tsiz: 0x1f98
hsiz: 0x18
pbl: 0x0dcc2464
bdba: 0x02000010
     76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x1f5c
avsp=0x1f64
tosp=0x1f65
0xe:pti[0]      nrow=3  offs=0
0x12:pri[0]     offs=0x1f5c
0x14:pri[1]     offs=0x1f88
0x16:pri[2]     offs=0x1f80
block_row_dump:
tab 0, row 0, @0x1f5c
tl: 8 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 02
col  1: [ 1]  61
tab 0, row 1, @0x1f88
tl: 8 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 03
col  1: [ 1]  62
tab 0, row 2, @0x1f80
tl: 8 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 04
col  1: [ 1]  63
end_of_block_dump
End dump data blocks tsn: 10 file#: 8 minblk 16 maxblk 16

這個dump文件開頭對數據庫的環境做了一些描述,中間是一些16進制的內容,最后面是事務和行的一些信息,任何一個事務想修改數據塊,都必需要獲取一個Itl:

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0004.005.00000c41  0x00800c4a.0692.13  ----    1  fsc 0x0001.00000000
0x02   0x0003.01b.00000cfe  0x008006d1.072a.04  C---    0  scn 0x0000.01151109

看上面的事務的信息,查看Flag,4個'-'代表有一個事務正在修改數據塊,Lck代表當前鎖定了一條數據,Itl=0x01,其實對應的就是下面的:

tab 0, row 0, @0x1f5c
tl: 8 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 02
col  1: [ 1]  61

當為0x1狀態時,表明該條數據已經被鎖定,加了TX鎖,其他事務想訪問它的時候會被阻塞..

(7)從這個時候Oracle數據塊的強大開始體現出來,如果是其他數據塊(如sqlserver)的話,那么就會等待,而Oracle的一致性讀很牛逼的解決了這個問題,它不讓阻塞,而是讓其他session去undo段里讀,具體的undo地址就是Uba(undo block address)所指示的地址:0x00800c4a.0692.13

我們對這個地址進行轉換,查詢它具體是哪個文件的哪個塊,首先將16進制轉換為10進制,再用相應的工具包進行轉換查詢:

SQL> select to_number('00800c4a','xxxxxxxx') from dual;

TO_NUMBER('0080B673','XXXXXXXX')
--------------------------------
                         8391754

SQL> select dbms_utility.data_block_address_file(8391754) as file#,
  2         dbms_utility.data_block_address_block(8391754) as block#
  3    from dual;

     FILE#     BLOCK#
---------- ----------
         2      3146

 

這下很清晰的查看到了,是在第2個數據文件的,第3146塊上,再查詢下第2個數據文件是啥文件

SQL> select tablespace_name,file_id from dba_data_files where file_id=2;

TABLESPACE_NAME                   FILE_ID
------------------------------ ----------
UNDOTBS1                                2

哈,這下更清晰了,那個地址指向的就是undo表空間里面的數據塊!

(8)再根據數據文件號和數據塊進行dump:

SQL> select tablespace_name,file_id from dba_data_files where file_id=2;

TABLESPACE_NAME                   FILE_ID
------------------------------ ----------
UNDOTBS1                                2

SQL> alter system dump datafile 2 block 3146;

System altered.

SQL> SELECT d.VALUE || '/' || LOWER(RTRIM(i.INSTANCE, CHR(0))) || '_ora_' ||
  2         p.spid || '.trc' trace_file_name
  3    FROM (SELECT p.spid
  4            FROM v$mystat m, v$session s, v$process p
  5           WHERE m.statistic# = 1
  6             AND s.SID = m.SID
  7             AND p.addr = s.paddr) p,
  8         (SELECT t.INSTANCE
  9            FROM v$thread t, v$parameter v
 10           WHERE v.NAME = 'thread'
 11             AND (v.VALUE = 0 OR t.thread# = TO_NUMBER(v.VALUE))) i,
 12         (SELECT VALUE FROM v$parameter WHERE NAME = 'user_dump_dest') d;

TRACE_FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oracle/admin/pmisdb/udump/pmisdb_ora_4113.trc

(9)查看dump undo出來的文件:

Dump file /u01/app/oracle/admin/pmisdb/udump/pmisdb_ora_4113.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      pmiscs
Release:        2.6.18-92.el5
Version:        #1 SMP Tue Apr 29 13:16:12 EDT 2008
Machine:        i686
Instance name: pmisdb
Redo thread mounted by this instance: 1
Oracle process number: 24
Unix process pid: 4113, image: oracle@pmiscs (TNS V1-V3)

*** ACTION NAME:() 2012-09-25 13:31:36.874
*** MODULE NAME:(sqlplus@pmiscs (TNS V1-V3)) 2012-09-25 13:31:36.874
*** SERVICE NAME:(SYS$USERS) 2012-09-25 13:31:36.874
*** SESSION ID:(523.77) 2012-09-25 13:31:36.874
Start dump data blocks tsn: 1 file#: 2 minblk 3146 maxblk 3146
buffer tsn: 1 rdba: 0x00800c4a (2/3146)
scn: 0x0000.0117548c seq: 0x01 flg: 0x04 tail: 0x548c0201
frmt: 0x02 chkval: 0x3970 type: 0x02=KTU UNDO BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0E101400 to 0x0E103400

...

********************************************************************************
UNDO BLK:  
xid: 0x0004.005.00000c41  seq: 0x692 cnt: 0x13  irb: 0x13  icl: 0x0   flg: 0x0000
 
 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
---------------------------------------------------------------------------
0x01 0x1f94     0x02 0x1eac     0x03 0x1e04     0x04 0x1d68     0x05 0x1d04     
0x06 0x1c68     0x07 0x1c04     0x08 0x1ba8     0x09 0x1b54     0x0a 0x1af8     
0x0b 0x1aa4     0x0c 0x1a48     0x0d 0x19f4     0x0e 0x1900     0x0f 0x18b4     
0x10 0x17f0     0x11 0x178c     0x12 0x1738     0x13 0x1684     
 
*-----------------------------
* Rec #0x1  slt: 0x01  objn: 519(0x00000207)  objd: 519  tblspc: 0(0x00000000)
*       Layer:  10 (Index)   opc: 22   rci 0x00   
Undo type:  Regular undo   Last buffer split:  No 
Temp Object:  No 
Tablespace Undo:  No 
rdba: 0x00800c49
*-----------------------------
index undo for leaf key operations
KTB Redo 
op: 0x02  ver: 0x01  
op: C  uba: 0x00800c49.0692.2f
Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x401029 block=0x0040f182
(kdxlpu): purge leaf row
key :(10):  06 c5 2b 5f 60 0d 0e 02 c1 1d

...

 
*-----------------------------
* Rec #0x12  slt: 0x28  objn: 5141(0x00001415)  objd: 5141  tblspc: 0(0x00000000)
*       Layer:  10 (Index)   opc: 22   rci 0x11   
Undo type:  Regular undo   Last buffer split:  No 
Temp Object:  No 
Tablespace Undo:  No 
rdba: 0x00000000
*-----------------------------
index undo for leaf key operations
KTB Redo 
op: 0x02  ver: 0x01  
op: C  uba: 0x00800c4a.0692.11
Dump kdilk : itl=3, kdxlkflg=0x1 sdc=0 indexid=0x402b51 block=0x00402b52
(kdxlpu): purge leaf row
key :(10):  02 c1 04 06 00 40 2b 2a 00 08
 
*-----------------------------
* Rec #0x13  slt: 0x05  objn: 69998(0x0001116e)  objd: 69998  tblspc: 10(0x0000000a)
*       Layer:  11 (Row)   opc: 1   rci 0x00   
Undo type:  Regular undo    Begin trans    Last buffer split:  No 
Temp Object:  No 
Tablespace Undo:  No 
rdba: 0x00000000
*-----------------------------
uba: 0x00800c4a.0692.10 ctl max scn: 0x0000.0116f8c0 prv tx scn: 0x0000.0116f8d8
txn start scn: scn: 0x0000.0117548c logon user: 0
 prev brb: 8391750 prev bcl: 0
KDO undo record:
KTB Redo 
op: 0x04  ver: 0x01  
op: L  itl: xid:  0x0009.00f.00000a96 uba: 0x0080019d.0670.22
                      flg: C---    lkc:  0     scn: 0x0000.0114e6a3
KDO Op code: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x02000010  hdba: 0x0200000b
itli: 1  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 12
ncol: 2 nnew: 1 size: 2
col  1: [ 3]  61 2b 2b
 
End dump data blocks tsn: 1 file#: 2 minblk 3146 maxblk 3146

(10)怎么去讀這個dump文件,查找那條有事務的記錄呢?其實在上面undo地址Uba(undo block address)所指示的地址:0x00800c4a.0692.13,已經告訴我們了,0x00800c4a是16進制的地址,而13就是那條update的記錄!我們單獨把那條記錄拿出來:

*-----------------------------
* Rec #0x13  slt: 0x05  objn: 69998(0x0001116e)  objd: 69998  tblspc: 10(0x0000000a)
*       Layer:  11 (Row)   opc: 1   rci 0x00   
Undo type:  Regular undo    Begin trans    Last buffer split:  No 
Temp Object:  No 
Tablespace Undo:  No 
rdba: 0x00000000
*-----------------------------
uba: 0x00800c4a.0692.10 ctl max scn: 0x0000.0116f8c0 prv tx scn: 0x0000.0116f8d8
txn start scn: scn: 0x0000.0117548c logon user: 0
 prev brb: 8391750 prev bcl: 0
KDO undo record:
KTB Redo 
op: 0x04  ver: 0x01  
op: L  itl: xid:  0x0009.00f.00000a96 uba: 0x0080019d.0670.22
                      flg: C---    lkc:  0     scn: 0x0000.0114e6a3
KDO Op code: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x02000010  hdba: 0x0200000b
itli: 1  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 12
ncol: 2 nnew: 1 size: 2
col  1: [ 3]  61 2b 2b

 (11)對比session A dump出來的信息和從undo dump出來的信息:

--session A
col 1: [ 1] 61
--undo col
1: [ 3] 61 2b 2b

通過對比,可以發現session A的col1的值為61,undo里面的col1的值為61 2b 2b,把這2個值轉換成ascii碼:

SQL> select chr(to_number('61','xx')),chr(to_number('2b','xx')) from dual;

CH CH
-- --
a  + 

哈哈,這下清楚了.原來61代表的是'a',2b代表的'+'

(12)這樣,我們就把undo是怎么工作的實驗做完了.把原理再完整的描述一遍:session A對某條記錄做了dml操作,這個操作是在內存中完成的,這個時候在undo里面記錄一條信息,如果滿足了DBWn的條件那么就會寫入到磁盤中,不滿足的話就在內存中,在沒有提交之前,undo的信息一直不會被清除.session B在查詢該條記錄時,因為A沒有提交,所以在itl事務槽中對該條信息有一個記錄,會告訴session B去undo相應的地址查找該條記錄的內容,而不去使用內存中被改變的信息.這就是Oracle的一致性讀.

 

7.回過頭來,我們再看看相應的數據字典和動態性能視圖:

(1).在之前查找undo的文件和塊的地方,其實oracle已經給了我們一個視圖,告訴了我們相關的信息了

SQL> select t.UBAFIL,t.UBABLK from v$transaction t;

    UBAFIL     UBABLK
---------- ----------
         2       3146

(2).其他幾個動態性能視圖

SQL> select a.USN,a.XACTS from v$rollstat a where xacts <> 0;

       USN      XACTS
---------- ----------
         4          1

SQL> select segment_name from dba_rollback_segs where segment_id = 4;

SEGMENT_NAME
------------------------------
_SYSSMU4$

SQL> select * from dba_extents where segment_name = '_SYSSMU4$';
1  SYS  _SYSSMU4$    TYPE2 UNDO  UNDOTBS1  0  2  57  65536  8  2
2  SYS  _SYSSMU4$    TYPE2 UNDO  UNDOTBS1  1  2  225  65536  8  2
3  SYS  _SYSSMU4$    TYPE2 UNDO  UNDOTBS1  2  2  3081  1048576  128  2
4  SYS  _SYSSMU4$    TYPE2 UNDO  UNDOTBS1  3  2  2057  1048576  128  2

從v$rollstat的xacts不為0d記錄中可以得到當前能有事務的回滾段,根據回滾段號去dba_rollback_segs查找相應的名字,再根據名字去dba_extents去查找相應的信息,這樣一來,就把所有的知識都聯系起來了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM