oracle复制机制,深入讲解 oracle LOCK 内部机制

作者简介:

----------------------------------------------------

@ 孙显鹏,海天起点oracle技术专家,十年从业经验,

@ 拥有OCP 11G认证,精通oracle内部原理,擅长调优

@ 和解决疑难问题,致力于帮助客户解决生产过程中出

@ 现的问题,提高生产效率。

@ 爱好书法,周易,中医!

@ 微信号:sunyunyi_sun

@ 电  话--18629679269

-----------------------------------------------------

oracle LOCK 分为以下几种:

1:Data Dictionary Lock (DDL)

--row cache locks

--library cache locks and pins

2: Data Manipulation Locks (DML)

--Row locks

--table locks

3: internal locks and latches

4: Distributed locks

5: parallel cacle menagement (PCM) locks

讲解锁首先要说明enqueue,enqueue是一个service由Kernal Serive Enqueue (KSQ)层

提供服务,请求该servies被认为是client层,KSQ通过接口提供enqueue的请求,转换和

释放操作。enqueue是由资源和三个锁链表组成,这个我以前的文档详细讲解过,这里不做过多说明。

enqueue 的6中模式,以及模式之间的兼容性如下:

null

SS        =        Row Share (lock a row in shared mode)

SX        =        Row Exclusive (lock a row in exclusive mode)

S        =        Share (lock the entire table in shared mode)

SSX        =        Share Row Exclusive (lock the table in shared mode but a row in                exclusive)

X        =        Exclusive (lock the entire table in exclusive mode)

dd06a1abc3fb84da465ff4eff32374f6.gif

无标题.png (16.24 KB, 下载次数: 7)

2018-2-8 13:44 上传

enqueue分为 client enqueue和managed enqueue

client enqueue:

这也就是我们最常见遇见的enqueue:

1:TM--DML enqueue

2:TX--Transaction enqueue

3: User supplied

至于managed enqueue类型就是你从v$lock中看到的除了上面三个以外的,这部分锁我们不需要太多关心,

比如:BL,CF,CI.....

另外需要注意,enqueue中所有的锁结构都嵌入在SO中,方便进程死掉pmon进行恢复,这个可以通过dump process看到。

enqueue 的唯一号为

TYPE:为两个大写字符,比如TX,TM

ID1:ID2 为四个字节,依据TYPE不同有不同的值。

具体的值你可以从v$lock视图看到,基表为x$ksqeq,

资源信息你可以从v$resource中查询到,基表为x$ksqrs

比如我们常见的DML enqueue:

ID1表示object ID,ID2=0

TX enqueue:

ID1:高字节位表示事物的回滚段号,第字节位表示回滚段的槽号

ID2:表示序列号

很明显ID1-ID2表示事物的XID,这一点非常重要,因为在你分析死锁时,单机环境WFG信息比较容易分析,

rac环境下的WFG信息就会让有些人觉得看不懂,比如下面这个是RAC环境下的死锁WFG信息,

(关于死锁的分析我前面的文章已经详细解释过):

WFG 信息:

Global Wait-For-Graph(WFG) at ddTS[0.17ec] :

BLOCKED 70000140bd013b0 5 wq 2 cvtops x1 [0x1a20004][0x24f37],[TX] [1007-0076-01A3C9DD] 0

BLOCKER 70000140bd01260 5 wq 1 cvtops x8 [0x1a20004][0x24f37],[TX] [1014-014B-000031A9] 0

BLOCKED 70000140bb24858 5 wq 2 cvtops x1 [0x3ea0009][0x8d3c],[TX] [1014-014B-000031A9] 0

BLOCKER 70000140bb24708 5 wq 1 cvtops x8 [0x3ea0009][0x8d3c],[TX] [1007-0076-01A3C9DD] 0

* Cancel deadlock victim lockp xbd013b0

这个我们很明显看到是因为应用设计顺序问题导致两个资源被两个session互斥导致,应该修改应用设计问题。

我这里再啰嗦一次,

BLOCKED 表示被阻塞者,第三列的5就表示阻塞者请求X级锁,0-5,5表示X锁级别最高,TX也只有5级锁。

BLOCKER 表示持有者,同样他持有5级锁,一行和四行是一对互斥了,同样2行和3行也是互斥,就造成死锁。

当然这个是最常见的死锁,死锁的分类较多,比如ITL,BIT INDEX,外键无索引,自制事物等,各自锁的模式不同。

可能看不懂就是因为[TX] [1007-0076-01A3C9DD]信息,这个就代表XID,你往上看trace文件就会发现resource信息,

就是资源信息了,资源是什么东西呢?你要修改一行数据,修改的资源分为两部分,第一是这个表你首先添加SX锁,

防止有人DDL该表,另外你就获取TX锁,TX锁是存储在数据块的ITL信息中,这部分在我以前讲的事物解释中有详细

说明,dump 数据块就可以清楚的看到ITL信息,还有回滚段事物表信息,文章后面会有dump 数据块信息可以参照。

好了,基本理论说完了,我们看看例子:

T表我们只插入一行数据。

session 1(sid:223):

SQL> insert into t values (1,'sun');

1 row created.

SQL> commit;

Commit complete.

SQL> delete t;

1 row deleted.

session 2 (sid:130):

SQL> delete t;

等待锁....

session 3:

SQL> select sid,type,id1,id2,lmode,request from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

130 TX      65551       1087          0          6

223 TX      65551       1087          6          0

我们看到两个session 修改相同的行,这两个session的ID1和ID2是相同的,为什么?两个不同的session拥有相同的

XID,因为两个session修改的相同的行那么他们的ITL是一样的,XID肯定也是一样的,查询事物表:

SQL> select xid,XIDUSN,XIDSLOT,XIDSQN,STATUS from v$transaction;

XID                  XIDUSN    XIDSLOT     XIDSQN STATUS

---------------- ---------- ---------- ---------- ----------------

01000F003F040000          1         15       1087 ACTIVE

只存在一个事物,ID1=65551 二进制为:1 00000000 00001111  ,那么1111=15,前面=1,ID2=1087 对应XID号。

再来看看TM enqueue信息,还是上面的例子:

SQL> select sid,type,id1,id2,lmode,request from v$lock where type='TM';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

130 TM      89008          0          3          0

223 TM      89008          0          3          0

注意SX和SX是兼容的,你看没有锁等待,当然这个你也能从v$lock就可以直接查出object信息就是ID1

select object_name,object_type from dba_objects where object_id=89008

OBJECT_NAME          OBJECT_TYPE

-------------------- -------------------

T                    TABLE

enqueue基本上就说清楚了。

另外关于TX的问题比较复杂了,一个事物可以修改许多行,可以修改不同表,这些信息oracle怎么存储和识别呢?

这个就需要查看undo信息了,下面的例子看看一个事物修改两个表怎么在undo中存储旧的信息的。

session 1:

再建一张表:

SQL> create table T1 (id number);

Table created.

SQL> insert into t1 values (1);

1 row created.

SQL> commit;

select

dbms_rowid.rowid_relative_fno(rowid) ralative_fno,

dbms_rowid.rowid_block_number(rowid) block_number

from t;

RALATIVE_FNO BLOCK_NUMBER

------------ ------------

4          188

select

dbms_rowid.rowid_relative_fno(rowid) ralative_fno,

dbms_rowid.rowid_block_number(rowid) block_number

from t1;

RALATIVE_FNO BLOCK_NUMBER

------------ ------------

4          172

开始事物:这里删除t和t1表,两个表都只有一行数据

SQL> delete t;

1 row deleted.

SQL> delete t1;

1 row deleted.

session 2: 看看enqueue信息

SQL> select sid,type,id1,id2,lmode,request from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

223 TX     655391       1546          6          0

SQL> select sid,type,id1,id2,lmode,request from v$lock where type='TM';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

223 TM      89008          0          3          0

223 TM      89052          0          3          0

SQL>  select xid,XIDUSN,XIDSLOT,XIDSQN,STATUS from v$transaction;

XID                  XIDUSN    XIDSLOT     XIDSQN STATUS

---------------- ---------- ---------- ---------- ----------------

0A001F000A060000         10         31       1546 ACTIVE

dump 数据文件中数据块的信息:

alter system dump datafile 4 block 188;

Object id on Block? Y

seg/obj: 0x15bb0  csc: 0x00.1680ff  itc: 2  flg: E  typ: 1 - DATA

brn: 0  bdba: 0x10000b8 ver: 0x01 opc: 0

inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x000a.016.000005fb  0x00c00115.0199.17  C---    0  scn 0x0000.001680f6

0x02   0x000a.01f.0000060a  0x00c00c37.019b.09  ----    1  fsc 0x0008.00000000

bdba: 0x010000bc

data_block_dump,data header at 0x2ae2b73b7a64

===============

tsiz: 0x1f98

hsiz: 0x16

pbl: 0x2ae2b73b7a64

76543210

flag=--------

ntab=1

nrow=2

frre=0

fsbo=0x16

fseo=0x1f52

avsp=0x1f78

tosp=0x1f82

0xe

4f06a01a81d5603cca001c0e92e5ebda.gifti[0]      nrow=2  offs=0

0x12

4f06a01a81d5603cca001c0e92e5ebda.gifri[0]     sfll=-1

0x14

4f06a01a81d5603cca001c0e92e5ebda.gifri[1]     offs=0x1f52

block_row_dump:

tab 0, row 1, @0x1f52

tl: 2 fb: --HDFL-- lb: 0x2

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 188 maxblk 188

alter system dump datafile 4 block 172;

Block header dump:  0x010000ac

Object id on Block? Y

seg/obj: 0x15bdc  csc: 0x00.169657  itc: 2  flg: E  typ: 1 - DATA

brn: 0  bdba: 0x10000a8 ver: 0x01 opc: 0

inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0007.021.00000451  0x00c00444.00c2.05  C---    0  scn 0x0000.0016960c

0x02   0x000a.01f.0000060a  0x00c00c37.019b.0b  ----    1  fsc 0x0007.00000000

bdba: 0x010000ac

data_block_dump,data header at 0x2b16f82c0a64

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x2b16f82c0a64

76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f92

avsp=0x1f7b

tosp=0x1f84

0xe

4f06a01a81d5603cca001c0e92e5ebda.gifti[0]      nrow=1  offs=0

0x12

4f06a01a81d5603cca001c0e92e5ebda.gifri[0]     offs=0x1f92

block_row_dump:

tab 0, row 0, @0x1f92

tl: 2 fb: --HDFL-- lb: 0x2

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 172 maxblk 172

XID:0x000a.01f.0000060a --一个事物那么两个数据块的XID号都一样

Uba:

0x00c00c37.019b.09

0x00c00c37.019b.0b

注意Uba号的rec是不一样的,一个REC为9,一个REc为 b,在trace文件中可以找到:

select to_number('00c','xxx')/4 from dual;--3

select to_number('00c37','xxxxx') from dual;--3127

alter system dump datafile 3 block 3127;

*-----------------------------

* Rec #0x9  slt: 0x1f  objn: 89008(0x00015bb0)  objd: 89008  tblspc: 4(0x00000004)

*       Layer:  11 (Row)   opc: 1   rci 0x00

Undo type:  Regular undo    Begin trans    Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

rdba: 0x00000000Ext idx: 0

flg2: 0

*-----------------------------

uba: 0x00c00c37.019b.08 ctl max scn: 0x0000.001694e1 prv tx scn: 0x0000.001694e6

txn start scn: scn: 0x0000.0016960c logon user: 86

prev brb: 12586035 prev bcl: 0

KDO undo record:

KTB Redo

op: 0x04  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: L  itl: xid:  0x0009.01c.00000510 uba: 0x00c00184.012c.20

flg: C---    lkc:  0     scn: 0x0000.00155cc2

KDO Op code: IRP row dependencies Disabled

xtype: XA flags: 0x00000000  bdba: 0x010000bc  hdba: 0x010000ba

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 1(0x1) size/delt: 10

fb: --H-FL-- lb: 0x0  cc: 2

null: --

col  0: [ 2]  c1 02

col  1: [ 3]  73 75 6e   --t表存在两列。

我在这里解释下上面列的含义,undo块存储的是删除前的旧值,我们转换以下:

t表只有一行数据,值为 1,sun,注意dump函数使用方法,也就是datafile里面就是

这样存储数据的。

SQL> select dump(1,16) from dual;

DUMP(1,16)

-----------------

Typ=2 Len=2: c1,2

select dump('s',16) from dual;

DUMP('S',16)

----------------

Typ=96 Len=1: 73

select dump('u',16) from dual;

DUMP('U',16)

----------------

Typ=96 Len=1: 75

select dump('n',16) from dual;

DUMP('N',16)

----------------

Typ=96 Len=1: 6e

type 2 为number型,type 96为 varcher2,len为长度,后面为具体值。

下面就不转换了。

*-----------------------------

* Rec #0xb  slt: 0x1f  objn: 89052(0x00015bdc)  objd: 89052  tblspc: 4(0x00000004)

*       Layer:  11 (Row)   opc: 1   rci 0x0a

Undo type:  Regular undo   Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

rdba: 0x00000000

*-----------------------------

KDO undo record:

KTB Redo

op: 0x03  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: Z

KDO Op code: IRP row dependencies Disabled

xtype: XA flags: 0x00000000  bdba: 0x010000ac  hdba: 0x010000aa

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 0(0x0) size/delt: 6

fb: --H-FL-- lb: 0x0  cc: 1

null: -

col  0: [ 2]  c1 02--T1表只有一列。

End dump data blocks tsn: 2 file#: 3 minblk 3127 maxblk 3127

从undo块的内容可以看到,一个事物修改了不同表的行,

oracle将这两个行的undo信息存储在一个undo数据块里,并不是一个undo块

就是数据块的copy并修改其内容的,那是cr块的copy。所以说一个事物就只是对应

一个事物槽号,至于这个槽里面有多少个undo块,那就看你的事物修改了多少行数据,

修改越多那么undo块就越多,当然了该undo段也就越大。从后面undo段头的事物表你就

可以看到事物表最多容纳0x21也就是34个事物。

其实上面undo块的信息和redo信息一样,redo更详细,我们看看redo的dump信息:

alter system dump logfile '/u01/app/oracle/oradata/orainfa/redo02.log'

op: F  xid:  0x000a.01f.0000060a    uba: 0x00c00c37.019b.09---看到了吧,XID 和 uba信息和上面对应看。

KDO Op code: DRP row dependencies Disabled

xtype: XA flags: 0x00000000  bdba: 0x010000bc  hdba: 0x010000ba

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 1(0x1)

CHANGE #2 TYP:0 CLS:35 AFN:3 DBA:0x00c00110--undo段头地址 OBJ:4294967295 SCN:0x0000.00169642 SEQ:1 OP:5.2 ENC:0 RBL:0

ktudh redo: slt: 0x001f sqn: 0x0000060a flg: 0x0012 siz: 180 fbi: 0

uba: 0x00c00c37.019b.09    pxid:  0x0000.000.00000000

CHANGE #3 TYP:0 CLS:36 AFN:3 DBA:0x00c00c37 OBJ:4294967295 SCN:0x0000.00169641 SEQ:1 OP:5.1 ENC:0 RBL:0

ktudb redo: siz: 180 spc: 6982 flg: 0x0012 seq: 0x019b rec: 0x09

xid:  0x000a.01f.0000060a

ktubl redo: slt: 31 rci: 0 opc: 11.1 [objn: 89008 objd: 89008 tsn: 4]

Undo type:  Regular undo        Begin trans    Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

0x00000000  prev ctl uba: 0x00c00c37.019b.08

prev ctl max cmt scn:  0x0000.001694e1  prev tx cmt scn:  0x0000.001694e6

txn start scn:  0x0000.0016960c  logon user: 86  prev brb: 12586035  prev bcl: 0 BuExt idx: 0 flg2: 0

KDO undo record:

KTB Redo

op: 0x04  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: L  itl: xid:  0x0009.01c.00000510 uba: 0x00c00184.012c.20

flg: C---    lkc:  0     scn: 0x0000.00155cc2

KDO Op code: IRP row dependencies Disabled

xtype: XA flags: 0x00000000  bdba: 0x010000bc  hdba: 0x010000ba

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 1(0x1) size/delt: 10

fb: --H-FL-- lb: 0x0  cc: 2

null: --

col  0: [ 2]  c1 02

col  1: [ 3]  73 75 6e --和undo块信息一样,不再啰嗦了

我们dump undo 段头的事物表:

DBA:0x00c00110--undo段头地址

select to_number('00c','xxx')/4 from dual;--3

select to_number('00110','xxxxx') from dual;--272

alter system dump datafile 3 block 272;

TRN TBL:事物表

index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt

------------------------------------------------------------------------------------------------

0x00    9    0x00  0x060a  0x000b  0x0000.0016963e  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  1518056636

0x01    9    0x00  0x0609  0x0018  0x0000.0016955f  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056356

0x02    9    0x00  0x060a  0x0005  0x0000.00169534  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056298

0x03    9    0x00  0x0609  0x0011  0x0000.001695a3  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056444

0x04    9    0x00  0x060a  0x0012  0x0000.00169546  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056317

0x05    9    0x00  0x060a  0x0015  0x0000.0016953b  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056308

0x06    9    0x00  0x0609  0x001b  0x0000.00169595  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056428

0x07    9    0x00  0x0609  0x0002  0x0000.0016952a  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056284

0x08    9    0x00  0x0609  0x0006  0x0000.0016958b  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056420

0x09    9    0x00  0x0608  0x0004  0x0000.00169544  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056317

0x0a    9    0x00  0x0609  0x0001  0x0000.0016955d  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056356

0x0b    9    0x00  0x0608  0xffff  0x0000.00169642  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  1518056636

0x0c    9    0x00  0x0609  0x000a  0x0000.00169559  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056348

0x0d    9    0x00  0x060a  0x0016  0x0000.001695df  0x00c00c35  0x0000.000.00000000  0x00000001   0x00000000  1518056524

0x0e    9    0x00  0x060b  0x001c  0x0000.00169609  0x00c00c35  0x0000.000.00000000  0x00000001   0x00000000  1518056557

0x0f    9    0x00  0x060b  0x0003  0x0000.0016959e  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056436

0x10    9    0x00  0x0609  0x000e  0x0000.00169606  0x00c00c36  0x0000.000.00000000  0x00000001   0x00000000  1518056557

0x11    9    0x00  0x0607  0x001a  0x0000.001695b5  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056476

0x12    9    0x00  0x0609  0x0019  0x0000.0016954f  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056332

0x13    9    0x00  0x0609  0x000d  0x0000.001695db  0x00c00c35  0x0000.000.00000000  0x00000001   0x00000000  1518056516

0x14    9    0x00  0x0609  0x0010  0x0000.00169605  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  1518056557

0x15    9    0x00  0x0609  0x0009  0x0000.00169542  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056316

0x16    9    0x00  0x0608  0x001d  0x0000.001695e7  0x00c00c35  0x0000.000.00000000  0x00000001   0x00000000  1518056538

0x17    9    0x00  0x0609  0x0021  0x0000.00169517  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056268

0x18    9    0x00  0x0608  0x0008  0x0000.0016956f  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056380

0x19    9    0x00  0x0609  0x000c  0x0000.00169554  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056340

0x1a    9    0x00  0x060a  0x0013  0x0000.001695c6  0x00000000  0x0000.000.00000000  0x00000000   0x00000000  1518056492

0x1b    9    0x00  0x0609  0x000f  0x0000.0016959a  0x00c00c34  0x0000.000.00000000  0x00000001   0x00000000  1518056436

0x1c    9    0x00  0x060a  0x0000  0x0000.00169614  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  1518056572

0x1d    9    0x00  0x0604  0x0014  0x0000.00169603  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  1518056557

0x1e    9    0x00  0x0608  0x0017  0x0000.0016950e  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056252

0x1f   10    0x80  0x060a  0x0002  0x0000.0016960c  0x00c00c37  0x0000.000.00000000  0x00000001   0x00000000  0

0x20    9    0x00  0x0609  0x001e  0x0000.001694fd  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056228

0x21    9    0x00  0x0609  0x0007  0x0000.0016951e  0x00c00c33  0x0000.000.00000000  0x00000001   0x00000000  1518056277

0x1f --这就是我们事物的槽号,SNC=0x0000.0016960c UNDO 块=0x00c00c37 就是我们上面dump的信息

至于oracle的其他锁,enqueue的结构是一模一样的,比如buffer lock的资源结构就是buffer header,lock结构就是buffer handle。

row cache lock 和 library cache locks and pins 你就找他的资源和lock结构就可以完全弄明白每个enqueue的结构,这样你对oracle

的内存架构就会有一个深入的认识,遇到问题思路就比较开阔。另外一定要对oracle的架构有一个层级关系认识这点非常重要。

2018-02-08 今天是儿子的生日,祝愿劭航:生日快乐!学业有成!

孙显鹏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值