MySQLInnoDB之MVCC原理是什么

今天小編給大家分享一下MySQL InnoDB之MVCC原理是什么的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

成都創(chuàng)新互聯(lián)專注于管城企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城網(wǎng)站建設(shè)。管城網(wǎng)站建設(shè)公司,為管城等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

MySQL InnoDB之MVCC原理是什么

MVCC全稱Multi-Version Concurrency Control,即多版本并發(fā)控制,主要是為了提高數(shù)據(jù)庫的并發(fā)性能。同一行數(shù)據(jù)平時(shí)發(fā)生讀寫請(qǐng)求時(shí),會(huì)上鎖阻塞住。但MVCC用更好的方式去處理讀—寫請(qǐng)求,做到在發(fā)生讀—寫請(qǐng)求沖突時(shí)不用加鎖。這個(gè)讀是指的快照讀,而不是當(dāng)前讀,當(dāng)前讀是一種加鎖操作,是悲觀鎖。那它到底是怎么做到讀—寫不用加鎖的,快照讀和當(dāng)前讀是指什么?我們后面都會(huì)學(xué)到。

MySQL在REPEATABLE READ隔離級(jí)別下,是可以很大程度避免幻讀問題的發(fā)生的,MySQL是怎么做到的?

版本鏈

我們知道,對(duì)于使用InnoDB存儲(chǔ)引擎的表來說,它的聚簇索引記錄中都包含兩個(gè)必要的隱藏列(row_id并不是必要的,我們創(chuàng)建的表中有主鍵或者非NULL的UNIQUE鍵時(shí)都不會(huì)包含row_id列):

  • trx_id:每次一個(gè)事務(wù)對(duì)某條聚簇索引記錄進(jìn)行改動(dòng)時(shí),都會(huì)把該事務(wù)的事務(wù)id賦值給trx_id隱藏列。

  • roll_pointer:每次對(duì)某條聚簇索引記錄進(jìn)行改動(dòng)時(shí),都會(huì)把舊的版本寫入到undo日志中,然后這個(gè)隱藏列就相當(dāng)于一個(gè)指針,可以通過它來找到該記錄修改前的信息。

為了說明這個(gè)問題,我們創(chuàng)建一個(gè)演示表:

CREATE TABLE `teacher` (
  `number` int(11) NOT NULL,
  `name` varchar(100) DEFAULT NULL,
  `domain` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`number`)) ENGINE=InnoDB DEFAULT CHARSET=utf8

然后向這個(gè)表里插入一條數(shù)據(jù):

mysql> insert into teacher values(1, 'J', 'Java');Query OK, 1 row affected (0.01 sec)

現(xiàn)在里的數(shù)據(jù)就是這樣的:

mysql> select * from teacher;
+--------+------+--------+
| number | name | domain |
+--------+------+--------+
|      1 | J    | Java   |
+--------+------+--------+
1 row in set (0.00 sec)

假設(shè)插入該記錄的事務(wù)id為60,那么此刻該條記錄的示意圖如下所示:

MySQL InnoDB之MVCC原理是什么

假設(shè)之后兩個(gè)事務(wù)id分別為80、120的事務(wù)對(duì)這條記錄進(jìn)行UPDATE操作,操作流程如下:

Trx80Trx120
begin

begin
update teacher set name=‘S’ where number=1;
update teacher set name=‘T’ where number=1;
commit

update teacher set name=‘K’ where number=1;

update teacher set name=‘F’ where number=1;

commit

每次對(duì)記錄進(jìn)行改動(dòng),都會(huì)記錄一條undo日志,每條undo日志也都有一個(gè)roll_pointer屬性(INSERT操作對(duì)應(yīng)的undo日志沒有該屬性,因?yàn)樵撚涗洸]有更早的版本),可以將這些undo日志都連起來,串成一個(gè)鏈表,所以現(xiàn)在的情況就像下圖一樣:

MySQL InnoDB之MVCC原理是什么

對(duì)該記錄每次更新后,都會(huì)將舊值放到一條undo日志中,就算是該記錄的一個(gè)舊版本,隨著更新次數(shù)的增多,所有的版本都會(huì)被roll_pointer屬性連接成一個(gè)鏈表,我們把這個(gè)鏈表稱之為版本鏈,版本鏈的頭節(jié)點(diǎn)就是當(dāng)前記錄最新的值。另外,每個(gè)版本中還包含生成該版本時(shí)對(duì)應(yīng)的事務(wù)id。于是可以利用這個(gè)記錄的版本鏈來控制并發(fā)事務(wù)訪問相同記錄的行為,那么這種機(jī)制就被稱之為多版本并發(fā)控制(Mulit-Version Concurrency Control MVCC)。

ReadView

對(duì)于使用READ UNCOMMITTED隔離級(jí)別的事務(wù)來說,由于可以讀到未提交事務(wù)修改過的記錄,所以直接讀取記錄的最新版本就好了。

對(duì)于使用SERIALIZABLE隔離級(jí)別的事務(wù)來說,InnoDB使用加鎖的方式來訪問記錄。

對(duì)于使用READ COMMITTED和REPEATABLE READ隔離級(jí)別的事務(wù)來說,都必須保證讀到已經(jīng)提交了的事務(wù)修改過的記錄,也就是說假如另一個(gè)事務(wù)已經(jīng)修改了記錄但是尚未提交,是不能直接讀取最新版本的記錄的,核心問題就是:READ COMMITTED和REPEATABLE READ隔離級(jí)別在不可重復(fù)讀和幻讀上的區(qū)別,這兩種隔離級(jí)別關(guān)鍵是需要判斷一下版本鏈中的哪個(gè)版本是當(dāng)前事務(wù)可見的。

為此,InnoDB提出了一個(gè)ReadView的概念,這個(gè)ReadView中主要包含4個(gè)比較重要的內(nèi)容:

  • m_ids:表示在生成ReadView時(shí)當(dāng)前系統(tǒng)中活躍的讀寫事務(wù)的事務(wù)id列表。

  • min_trx_id:表示在生成ReadView時(shí)當(dāng)前系統(tǒng)中活躍的讀寫事務(wù)中最小的事務(wù)id,也就是m_ids中的最小值。

  • max_trx_id:表示生成ReadView時(shí)系統(tǒng)中應(yīng)該分配給下一個(gè)事務(wù)的id值。注意max_trx_id并不是m_ids中的最大值,事務(wù)id是遞增分配的。比方說現(xiàn)在有id為1,2,3這三個(gè)事務(wù),之后id為3的事務(wù)提交了。那么一個(gè)新的讀事務(wù)在生成ReadView時(shí),m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。

  • creator_trx_id:表示生成該ReadView的事務(wù)的事務(wù)id。

有了這個(gè)ReadView,這樣在訪問某條記錄時(shí),只需要按照下邊的步驟判斷記錄的某個(gè)版本是否可見:

  1. 如果被訪問版本的trx_id屬性值與ReadView中的creator_trx_id值相同,意味著當(dāng)前事務(wù)在訪問它自己修改過的記錄,所以該版本可以被當(dāng)前事務(wù)訪問。

  2. 如果被訪問版本的trx_id屬性值小于ReadView中的min_trx_id值,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成ReadView前已經(jīng)提交,所以該版本可以被當(dāng)前事務(wù)訪問。

  3. 如果被訪問版本的trx_id屬性值大于或等于ReadView中的max_trx_id值,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成ReadView后才開啟,所以該版本不可以被當(dāng)前事務(wù)訪問。

  4. 如果被訪問版本的trx_id屬性值在ReadView的min_trx_id和max_trx_id之間(min_trx_id <= trx_id < max_trx_id),那就需要判斷一下trx_id屬性值是不是在m_ids列表中,如果在,說明創(chuàng)建ReadView時(shí)生成該版本的事務(wù)還是活躍的,事務(wù)還沒提交,該版本不可以被訪問;如果不在,說明創(chuàng)建ReadView時(shí)生成該版本的事務(wù)已經(jīng)被提交,該版本可以被訪問。

  5. 如果某個(gè)版本的數(shù)據(jù)對(duì)當(dāng)前事務(wù)不可見的話,那就順著版本鏈找到下一個(gè)版本的數(shù)據(jù),繼續(xù)按照上邊的步驟判斷可見性,依此類推,直到版本鏈中的最后一個(gè)版本。如果最后一個(gè)版本也不可見的話,那么就意味著該條記錄對(duì)該事務(wù)完全不可見,查詢結(jié)果就不包含該記錄。

在MySQL中,READ COMMITTED和REPEATABLE READ隔離級(jí)別的的一個(gè)非常大的區(qū)別就是它們生成ReadView的時(shí)機(jī)不同。

我們還是以表teacher為例,假設(shè)現(xiàn)在表teacher中只有一條由事務(wù)id為60的事務(wù)插入的一條記錄,接下來看一下READ COMMITTED和REPEATABLE READ所謂的生成ReadView的時(shí)機(jī)不同到底不同在哪里。

READ COMMITTED每次讀取數(shù)據(jù)前都生成一個(gè)ReadView

假設(shè)現(xiàn)在系統(tǒng)里有兩個(gè)事務(wù)id分別為80、120的事務(wù)在執(zhí)行:

# Transaction 80
set session transaction isolation level read committed;
begin
update teacher set name='S' where number=1;
update teacher set name='T' where number=1;

此刻,表teacher中number為1的記錄得到的版本鏈表如下所示:

MySQL InnoDB之MVCC原理是什么

假設(shè)現(xiàn)在有一個(gè)使用READ COMMITTED隔離級(jí)別的事務(wù)開始執(zhí)行:

set session transaction isolation level read committed;
# 使用READ COMMITTED隔離級(jí)別的事務(wù)
begin;
# SELECE1:Transaction 80、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'J'

這個(gè)SELECE1的執(zhí)行過程如下:

  • 在執(zhí)行SELECT語句時(shí)會(huì)先生成一個(gè)ReadView,ReadView的m_ids列表的內(nèi)容就是[80, 120],min_trx_id為80,max_trx_id為121,creator_trx_id為0。

  • 然后從版本鏈中挑選可見的記錄,最新版本的列name的內(nèi)容是’T’,該版本的trx_id值為80,在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’S’,該版本的trx_id值也為80,也在m_ids列表內(nèi),根據(jù)步驟4也不符合要求,繼續(xù)跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’J’,該版本的trx_id值為60,小于ReadView 中的min_trx_id值,根據(jù)步驟2判斷這個(gè)版本是符合要求的。

之后,我們把事務(wù)id為80的事務(wù)提交一下,然后再到事務(wù)id為120的事務(wù)中更新一下表teacher 中number為1的記錄:

set session transaction isolation level read committed;
# Transaction 120
begin
update teacher set name='K' where number=1;
update teacher set name='F' where number=1;

此刻,表teacher 中number為1的記錄的版本鏈就長(zhǎng)這樣:

MySQL InnoDB之MVCC原理是什么

然后再到剛才使用READ COMMITTED隔離級(jí)別的事務(wù)中繼續(xù)查找這個(gè)number 為1的記錄,如下:

# 使用READ COMMITTED隔離級(jí)別的事務(wù)
begin;
# SELECE1:Transaction 80、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'J'
# SELECE2:Transaction 80提交、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'T'

這個(gè)SELECE2 的執(zhí)行過程如下:

  • 在執(zhí)行SELECT語句時(shí)會(huì)又會(huì)單獨(dú)生成一個(gè)ReadView,該ReadView的m_ids列表的內(nèi)容就是[120](事務(wù)id為80的那個(gè)事務(wù)已經(jīng)提交了,所以再次生成快照時(shí)就沒有它了),min_trx_id為120,max_trx_id為121,creator_trx_id為0。

  • 然后從版本鏈中挑選可見的記錄,從圖中可以看出,最新版本的列name的內(nèi)容是’F’,該版本的trx_id值為120,在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name 的內(nèi)容是’K’,該版本的trx_id值為120,也在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’T’,該版本的trx_id值為80,小于ReadView中的min_trx_id值120,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成ReadView前已經(jīng)提交,所以這個(gè)版本是符合要求的,最后返回給用戶的版本就是這條列name為’‘T’'的記錄。

以此類推,如果之后事務(wù)id為120的記錄也提交了,再次在使用READCOMMITTED隔離級(jí)別的事務(wù)中查詢表teacher中number值為1的記錄時(shí),得到的結(jié)果就是’F’了,具體流程我們就不分析了。

總結(jié)一下就是:使用READCOMMITTED隔離級(jí)別的事務(wù)在每次查詢開始時(shí)都會(huì)生成一個(gè)獨(dú)立的ReadView。

REPEATABLE READ —— 在第一次讀取數(shù)據(jù)時(shí)生成一個(gè)ReadView

對(duì)于使用REPEATABLE READ隔離級(jí)別的事務(wù)來說,只會(huì)在第一次執(zhí)行查詢語句時(shí)生成一個(gè)ReadView,之后的查詢就不會(huì)重復(fù)生成了。我們還是用例子看一下是什么效果。

假設(shè)現(xiàn)在系統(tǒng)里有兩個(gè)事務(wù)id分別為80、120的事務(wù)在執(zhí)行:

# Transaction 80
begin
update teacher set name='S' where number=1;
update teacher set name='T' where number=1;

此刻,表teacher中number為1的記錄得到的版本鏈表如下所示:

MySQL InnoDB之MVCC原理是什么

假設(shè)現(xiàn)在有一個(gè)使用REPEATABLE READ隔離級(jí)別的事務(wù)開始執(zhí)行:

# 使用REPEATABLE READ隔離級(jí)別的事務(wù)
begin;
# SELECE1:Transaction 80、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'J'

這個(gè)SELECE1的執(zhí)行過程如下(與READ COMMITTED的過程一致):

  • 在執(zhí)行SELECT語句時(shí)會(huì)先生成一個(gè)ReadView,ReadView的m_ids列表的內(nèi)容就是[80, 120],min_trx_id為80,max_trx_id為121,creator_trx_id為0。

  • 然后從版本鏈中挑選可見的記錄,最新版本的列name的內(nèi)容是’T’,該版本的trx_id值為80,在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’S’,該版本的trx_id值也為80,也在m_ids列表內(nèi),根據(jù)步驟4也不符合要求,繼續(xù)跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’J’,該版本的trx_id值為60,小于ReadView 中的min_trx_id值,根據(jù)步驟2判斷這個(gè)版本是符合要求的。

之后,我們把事務(wù)id為80的事務(wù)提交一下,然后再到事務(wù)id為120的事務(wù)中更新一下表teacher 中number為1的記錄:

# Transaction 80
begin
update teacher set name='K' where number=1;
update teacher set name='F' where number=1;

此刻,表teacher 中number為1的記錄的版本鏈就長(zhǎng)這樣:

MySQL InnoDB之MVCC原理是什么

然后再到剛才使用REPEATABLE READ隔離級(jí)別的事務(wù)中繼續(xù)查找這個(gè)number為1的記錄,如下:

# 使用REPEATABLE READ隔離級(jí)別的事務(wù)
begin;
# SELECE1:Transaction 80、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'J'
# SELECE2:Transaction 80提交、120未提交
SELECT * FROM teacher WHERE number = 1; # 得到的列name的值為'J'

這個(gè)SELECE2的執(zhí)行過程如下:

  • 因?yàn)楫?dāng)前事務(wù)的隔離級(jí)別為REPEATABLE READ,而之前在執(zhí)行SELECE1時(shí)已經(jīng)生成過ReadView了,所以此時(shí)直接復(fù)用之前的ReadView,之前的ReadView的m_ids列表的內(nèi)容就是[80, 120],min_trx_id為80,max_trx_id為121,creator_trx_id為0。

  • 然后從版本鏈中挑選可見的記錄,從圖中可以看出,最新版本的列name的內(nèi)容是’F’,該版本的trx_id值為120,在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’K’,該版本的trx_id值為120,也在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’T’,該版本的trx_id值為80,也在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’S’,該版本的trx_id值為80,也在m_ids列表內(nèi),根據(jù)步驟4不符合可見性要求,根據(jù)roll_pointer跳到下一個(gè)版本。

  • 下一個(gè)版本的列name的內(nèi)容是’J’,該版本的trx_id值為60,小于ReadView中的min_trx_id值80,表明生成該版本的事務(wù)在當(dāng)前事務(wù)生成ReadView前已經(jīng)提交,所以這個(gè)版本是符合要求的,最后返回給用戶的版本就是這條列name為’‘J’'的記錄。

也就是說兩次SELECT查詢得到的結(jié)果是重復(fù)的,記錄的列值都是’’‘J’’’,這就是可重復(fù)讀的含義。

如果我們之后再把事務(wù)id為120的記錄提交了,然后再到剛才使用REPEATABLE READ隔離級(jí)別的事務(wù)中繼續(xù)查找這個(gè)number為1的記錄,得到的結(jié)果還是’J’,具體執(zhí)行過程大家可以自己分析一下。

MVCC下的幻讀現(xiàn)象和幻讀解決

前面我們已經(jīng)知道了,REPEATABLE READ隔離級(jí)別下MVCC可以解決不可重復(fù)讀問題,那么幻讀呢?MVCC是怎么解決的?幻讀是一個(gè)事務(wù)按照某個(gè)相同條件多次讀取記錄時(shí),后讀取時(shí)讀到了之前沒有讀到的記錄,而這個(gè)記錄來自另一個(gè)事務(wù)添加的新記錄。

我們可以想想,在REPEATABLE READ隔離級(jí)別下的事務(wù)T1先根據(jù)某個(gè)搜索條件讀取到多條記錄,然后事務(wù)T2插入一條符合相應(yīng)搜索條件的記錄并提交,然后事務(wù)T1再根據(jù)相同搜索條件執(zhí)行查詢。結(jié)果會(huì)是什么?按照ReadView中的比較規(guī)則:

不管事務(wù)T2比事務(wù)T1是否先開啟,事務(wù)T1都是看不到T2的提交的。請(qǐng)自行按照上面介紹的版本鏈、ReadView以及判斷可見性的規(guī)則來分析一下。

但是,在REPEATABLE READ隔離級(jí)別下InnoDB中的MVCC可以很大程度地避免幻讀現(xiàn)象,而不是完全禁止幻讀。怎么回事呢?我們來看下面的情況:

T1T2
begin;
select * from teacher where number=30; 無數(shù)據(jù)begin;

insert into teacher values(30, ‘X’, ‘Java’);

commit;
update teacher set domain=‘MQ’ where number=30;
select * from teacher where number = 30; 有數(shù)據(jù)

嗯,怎么回事?事務(wù)T1很明顯出現(xiàn)了幻讀現(xiàn)象。在REPEATABLE READ隔離級(jí)別下,T1第一次執(zhí)行普通的SELECT語句時(shí)生成了一個(gè)ReadView,之后T2向teacher表中新插入一條記錄并提交。ReadView并不能阻止T1執(zhí)行UPDATE或者DELETE語句來改動(dòng)這個(gè)新插入的記錄(由于T2已經(jīng)提交,因此改動(dòng)該記錄并不會(huì)造成阻塞),但是這樣一來,這條新記錄的trx_id隱藏列的值就變成了T1的事務(wù)id。之后T1再使用普通的SELECT語句去查詢這條記錄時(shí)就可以看到這條記錄了,也就可以把這條記錄返回給客戶端。因?yàn)檫@個(gè)特殊現(xiàn)象的存在,我們也可以認(rèn)為MVCC并不能完全禁止幻讀。

MVCC小結(jié)

從上邊的描述中我們可以看出來,所謂的MVCC(Multi-Version ConcurrencyControl ,多版本并發(fā)控制)指的就是在使用READ COMMITTD、REPEATABLE READ這兩種隔離級(jí)別的事務(wù)在執(zhí)行普通的SELECT操作時(shí)訪問記錄的版本鏈的過程,這樣子可以使不同事務(wù)的讀-寫、寫-讀操作并發(fā)執(zhí)行,從而提升系統(tǒng)性能。

READ COMMITTD、REPEATABLE READ這兩個(gè)隔離級(jí)別的一個(gè)很大不同就是:生成ReadView的時(shí)機(jī)不同,READ COMMITTD在每一次進(jìn)行普通SELECT操作前都會(huì)生成一個(gè)ReadView,而REPEATABLE READ只在第一次進(jìn)行普通SELECT操作前生成一個(gè)ReadView,之后的查詢操作都重復(fù)使用這個(gè)ReadView就好了,從而基本上可以避免幻讀現(xiàn)象。

我們之前說執(zhí)行DELETE語句或者更新主鍵的UPDATE語句并不會(huì)立即把對(duì)應(yīng)的記錄完全從頁面中刪除,而是執(zhí)行一個(gè)所謂的delete mark操作,相當(dāng)于只是對(duì)記錄打上了一個(gè)刪除標(biāo)志位,這主要就是為MVCC服務(wù)的。另外,所謂的MVCC只是在我們進(jìn)行普通的SEELCT查詢時(shí)才生效,截止到目前我們所見的所有SELECT語句都算是普通的查詢,至于什么是個(gè)不普通的查詢,后面就會(huì)講到。

以上就是“MySQL InnoDB之MVCC原理是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章題目:MySQLInnoDB之MVCC原理是什么
路徑分享:http://bm7419.com/article24/gocdce.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、網(wǎng)站制作、移動(dòng)網(wǎng)站建設(shè)、外貿(mào)建站網(wǎng)站設(shè)計(jì)、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管