自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

數(shù)據(jù)庫時(shí)間慢了14個(gè)小時(shí),Mybatis說,這個(gè)鍋我不背!

運(yùn)維 數(shù)據(jù)庫運(yùn)維
大家都知道,對(duì)于這類Bug本人是很感興趣的。直覺告訴我,應(yīng)該不是Mybatis的Bug,很可能是時(shí)區(qū)的問題。很好,今天又可以帶大家一起來排查Bug了,看看從這次的Bug排查中你能Get什么技能。

[[436824]]

本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者二師兄。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。

同事反饋一個(gè)問題:Mybatis插入數(shù)據(jù)庫的時(shí)間是昨天的,是不是因?yàn)樯蒑ybatis逆向工程生成的代碼有問題?

大家都知道,對(duì)于這類Bug本人是很感興趣的。直覺告訴我,應(yīng)該不是Mybatis的Bug,很可能是時(shí)區(qū)的問題。

很好,今天又可以帶大家一起來排查Bug了,看看從這次的Bug排查中你能Get什么技能。

這次研究的問題有點(diǎn)深?yuàn)W,但結(jié)論很重要。Let's go!

問題猜想

同事反饋問題的時(shí)候,帶了自己的猜想:是不是數(shù)據(jù)庫字段設(shè)置為datetime導(dǎo)致?是不是Mybatis逆向工程生成的代碼中類型不一致導(dǎo)致的?

同事還要把datetime改為varchar……馬上被我制止了,說:先排查問題,再說解決方案,下午我也抽時(shí)間看看。

問題核查

第一步,檢查數(shù)據(jù)庫字段類型,是datetime的,沒問題。

第二步,檢查實(shí)體類中類型,是java.util.Date類型,沒問題。

第三步,Bug復(fù)現(xiàn)。

在Bug復(fù)現(xiàn)這一步,用到了單元測(cè)試。話說之前還跟朋友討論過單元測(cè)試的魅力,現(xiàn)在本人是越來越喜歡單元測(cè)試了。

項(xiàng)目基于Spring Boot的,單元測(cè)試如下(代碼已脫敏):

  1. @SpringBootTest 
  2. class DateTimeTests { 
  3.  
  4.  @Resource 
  5.  private UserMapper userMapper; 
  6.  
  7.  @Test 
  8.  public void testDate(){ 
  9.   User  user = new User(); 
  10.   // 省略其他字段 
  11.   user.setCreateDate(new Date()); 
  12.   userMapper.insertSelective(user); 
  13.  } 

執(zhí)行單元測(cè)試,查看數(shù)據(jù)庫中插入的數(shù)據(jù)。Bug復(fù)現(xiàn),時(shí)間的確是前一天的,與當(dāng)前時(shí)間相差14個(gè)小時(shí)。

經(jīng)過上面三步的排查,核實(shí)了數(shù)據(jù)庫字段和代碼中類型沒問題。單元測(cè)試也復(fù)現(xiàn)了問題,同事沒有欺騙我,總要眼見為實(shí),哈哈。

于是基本確定是時(shí)區(qū)問題。

時(shí)區(qū)排查

檢查服務(wù)器時(shí)間

登錄測(cè)試服務(wù)器,執(zhí)行date命令,檢查服務(wù)器時(shí)間和時(shí)區(qū):

  1. [root@xxx ~]# date 
  2. 2021年 11月 25日 星期四 09:26:25 CST 
  3. [root@xxx ~]# date -R 
  4. Thu, 25 Nov 2021 09:33:34 +0800 

顯示時(shí)間是當(dāng)前時(shí)間,采用CST時(shí)間,最后的+0800,即東8區(qū),沒問題。

檢查數(shù)據(jù)庫時(shí)區(qū)

連接數(shù)據(jù)庫,執(zhí)行show命令:

  1. show variables like '%time_zone%'
  2.  
  3. +----------------------------+ 
  4. |Variable         | Value | 
  5. +----------------------------+ 
  6. |system_time_zone |CST    | 
  7. |time_zone       |SYSTEM | 
  • system_time_zone:全局參數(shù),系統(tǒng)時(shí)區(qū),在MySQL啟動(dòng)時(shí)會(huì)檢查當(dāng)前系統(tǒng)的時(shí)區(qū)并根據(jù)系統(tǒng)時(shí)區(qū)設(shè)置全局參數(shù)system_time_zone的值。值為CST,與系統(tǒng)時(shí)間的時(shí)區(qū)一致。
  • time_zone:全局參數(shù),設(shè)置每個(gè)連接會(huì)話的時(shí)區(qū),默認(rèn)為SYSTEM,使用全局參數(shù)system_time_zone的值。

檢查代碼中時(shí)區(qū)

在單元測(cè)試的方法內(nèi)再添加打印時(shí)區(qū)的代碼:

  1. @Test 
  2.  public void testDate(){ 
  3.   System.out.println(System.getProperty("user.timezone")); 
  4.   User  user = new User(); 
  5.   // 省略其他字段 
  6.   user.setCreateDate(new Date()); 
  7.   userMapper.insertSelective(user); 
  8.  } 

打印的時(shí)區(qū)為:

  1. Asia/Shanghai 

也就是說Java中使用的是UTC時(shí)區(qū)進(jìn)行業(yè)務(wù)邏輯處理的,也是東八區(qū)的時(shí)間。

那么問題到底出在哪里呢?

問題基本呈現(xiàn)

經(jīng)過上述排查,基本上確定是時(shí)區(qū)的問題。這里,再補(bǔ)充一下上述相關(guān)的時(shí)區(qū)知識(shí)點(diǎn)。

UTC時(shí)間

UTC時(shí)間:世界協(xié)調(diào)時(shí)間(UTC)是世界上不同國家用來調(diào)節(jié)時(shí)鐘和時(shí)間的主要時(shí)間標(biāo)準(zhǔn),也就是零時(shí)區(qū)的時(shí)間。

UTC, Coordinated Universal Time是一個(gè)標(biāo)準(zhǔn),而不是一個(gè)時(shí)區(qū)。UTC 是一個(gè)全球通用的時(shí)間標(biāo)準(zhǔn)。全球各地都同意將各自的時(shí)間進(jìn)行同步協(xié)調(diào) (coordinated),這也是UTC名字的來源:Universal Coordinated Time。

CST時(shí)間

CST時(shí)間:中央標(biāo)準(zhǔn)時(shí)間。

CST可以代表如下4個(gè)不同的時(shí)區(qū):

  • Central Standard Time (USA) UT-6:00,美國
  • Central Standard Time (Australia) UT+9:30,澳大利亞
  • China Standard Time UT+8:00,中國
  • Cuba Standard Time UT-4:00,古巴

再次分析

很顯然,這里與UTC時(shí)間無關(guān),它只是時(shí)間標(biāo)準(zhǔn)。目前Mysql中的system_time_zone是CST,而CST可以代表4個(gè)不同的時(shí)區(qū),那么,Mysql把它當(dāng)做哪個(gè)時(shí)區(qū)進(jìn)行處理了呢?

簡單推算一下,中國時(shí)間是UT+8:00,美國是 UT-6:00,當(dāng)傳入中國時(shí)間,直接轉(zhuǎn)換為美國時(shí)間(未考慮時(shí)區(qū)問題),時(shí)間便慢了14個(gè)小時(shí)。

既然知道了問題,那么解決方案也就有了。

解決方案

針對(duì)上述問題可通過數(shù)據(jù)庫層面和代碼層面進(jìn)行解決。

方案一:修改數(shù)據(jù)庫時(shí)區(qū)

既然是MySQL理解錯(cuò)了CST指定的時(shí)區(qū),那么就將其設(shè)置為正確的。

連接Mysql數(shù)據(jù)庫,設(shè)置正確的時(shí)區(qū):

  1. [root@xxxxx ~]# mysql -uroot -p 
  2.  
  3. mysql> set global time_zone = '+8:00'
  4.  
  5. mysql> set time_zone = '+8:00' 
  6.  
  7. mysql> flush privileges

再次執(zhí)行show命令:

  1. show variables like '%time_zone%'
  2.  
  3. +----------------------------+ 
  4. |Variable         | Value | 
  5. +----------------------------+ 
  6. |system_time_zone |CST    | 
  7. |time_zone       |+08:00 | 

可以看到時(shí)區(qū)已經(jīng)成為東八區(qū)的時(shí)間了。再次執(zhí)行單元測(cè)試,問題得到解決。

此種方案也可以直接修改MySQL的my.cnf文件進(jìn)行指定時(shí)區(qū)。

方案二:修改數(shù)據(jù)庫連接參數(shù)

在代碼連接數(shù)據(jù)庫時(shí),通過參數(shù)指定所使用的時(shí)區(qū)。

在配置數(shù)據(jù)庫連接的URL后面添加上指定的時(shí)區(qū)serverTimezone=Asia/Shanghai:

  1. url: jdbc:mysql://xx.xx.xx.xx:3306/db_name?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai 

再次執(zhí)行單元測(cè)試,問題同樣可以得到解決。

問題完了?

經(jīng)過上述分析與操作,時(shí)區(qū)的問題已經(jīng)解決了。問題就這么完事了嗎?為什么是這樣呢?

為了驗(yàn)證時(shí)區(qū)問題,在時(shí)區(qū)錯(cuò)誤的數(shù)據(jù)庫中,創(chuàng)建了一個(gè)字段,該字段類型為datetime,默認(rèn)值為CURRENT_TIMESTAMP。

那么,此時(shí)插入一條記錄,讓Mysql自動(dòng)生成該字段的時(shí)間,你猜該字段的時(shí)間是什么?中國時(shí)間。

神奇不?為什么同樣是CST時(shí)區(qū),系統(tǒng)自動(dòng)生成的時(shí)間是正確的,而代碼插入的時(shí)間就有時(shí)差問題呢?

到底是Mysql將CST時(shí)區(qū)理解為美國時(shí)間了,還是Mybatis、連接池或驅(qū)動(dòng)程序?qū)⑵淅斫鉃槊绹鴷r(shí)間了?

重頭戲開始

為了追查到底是代碼中哪里出了問題,先開啟Mybatis的debug日志,看看insert時(shí)是什么值:

  1. 2021-11-25 11:05:28.367 [|1637809527983|] DEBUG 20178 --- [   scheduling-1] c.h.s.m.H.listByCondition                : ==> Parameters: 2021-11-25 11:05:27(String), 0(Integer), 1(Integer), 2(Integer), 3(Integer), 4(Integer) 

上面是insert時(shí)的參數(shù),也就是說在Mybatis層面時(shí)間是沒問題的。排除一個(gè)。

那是不是連接池或驅(qū)動(dòng)程序的問題?連接池本身來講跟數(shù)據(jù)庫連接的具體操作關(guān)系不大,就直接來排查驅(qū)動(dòng)程序。

Mybatis是xml中定義日期字段類型為TIMESTAMP,扒了一下mysql-connector-Java-8.0.x的源碼,發(fā)現(xiàn)SqlTimestampValueFactory是用來處理TIMESTAMP類型的。

在SqlTimestampValueFactory的構(gòu)造方法上打上斷點(diǎn),執(zhí)行單元測(cè)試:

timezone

可以明確的看到,Calendar將時(shí)區(qū)設(shè)置為Locale.US,也就是美國時(shí)間,時(shí)區(qū)為CST,offset為-21600000。-21600000單位為毫秒,轉(zhuǎn)化為小時(shí),恰好是“-6:00”,這與北京時(shí)間“GMT+08:00”恰好相差14個(gè)小時(shí)。

于是一路往上最終追溯調(diào)用鏈路,該TimeZone來自NativeServerSession的serverTimeZone,而serverTimeZone的值是由NativeProtocol類的configureTimezone方法設(shè)置的。

  1. public void configureTimezone() { 
  2.         String configuredTimeZoneOnServer = this.serverSession.getServerVariable("time_zone"); 
  3.  
  4.         if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) { 
  5.             configuredTimeZoneOnServer = this.serverSession.getServerVariable("system_time_zone"); 
  6.         } 
  7.  
  8.         String canonicalTimezone = getPropertySet().getStringProperty(PropertyKey.serverTimezone).getValue(); 
  9.  
  10.         if (configuredTimeZoneOnServer != null) { 
  11.             // user can override this with driver properties, so don't detect if that's the case 
  12.             if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) { 
  13.                 try { 
  14.                     canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor()); 
  15.                 } catch (IllegalArgumentException iae) { 
  16.                     throw ExceptionFactory.createException(WrongArgumentException.class, iae.getMessage(), getExceptionInterceptor()); 
  17.                 } 
  18.             } 
  19.         } 
  20.  
  21.         if (canonicalTimezone != null && canonicalTimezone.length() > 0) { 
  22.          // 此處設(shè)置TimeZone 
  23.             this.serverSession.setServerTimeZone(TimeZone.getTimeZone(canonicalTimezone)); 
  24.  
  25.             if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverSession.getServerTimeZone().getID().equals("GMT")) { 
  26.                 throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[] { canonicalTimezone }), 
  27.                         getExceptionInterceptor()); 
  28.             } 
  29.         } 
  30.  
  31.     } 

debug跟蹤一下上述代碼,顯示信息如下:

CST獲得

至此,通過canonicalTimezone值的獲取,可以看出URL后面配置serverTimezone=Asia/Shanghai的作用了。其中,上面第一個(gè)代碼塊獲取time_zone的值,第二個(gè)代碼塊中獲取system_time_zone的值。這與查詢數(shù)據(jù)庫獲得的值一致。

因?yàn)槌鰡栴}時(shí)并未在url中添加參數(shù)serverTimezone=Asia/Shanghai,所以走canonicalTimezone為null的情況。隨后邏輯中調(diào)用了TimeUtil.getCanonicalTimezone方法:

  1. public static String getCanonicalTimezone(String timezoneStr, ExceptionInterceptor exceptionInterceptor) { 
  2.         if (timezoneStr == null) { 
  3.             return null
  4.         } 
  5.  
  6.         timezoneStr = timezoneStr.trim(); 
  7.  
  8.         // handle '+/-hh:mm' form ... 
  9.         if (timezoneStr.length() > 2) { 
  10.             if ((timezoneStr.charAt(0) == '+' || timezoneStr.charAt(0) == '-') && Character.isDigit(timezoneStr.charAt(1))) { 
  11.                 return "GMT" + timezoneStr; 
  12.             } 
  13.         } 
  14.  
  15.         synchronized (TimeUtil.class) { 
  16.             if (timeZoneMappings == null) { 
  17.                 loadTimeZoneMappings(exceptionInterceptor); 
  18.             } 
  19.         } 
  20.  
  21.         String canonicalTz; 
  22.         if ((canonicalTz = timeZoneMappings.getProperty(timezoneStr)) != null) { 
  23.             return canonicalTz; 
  24.         } 
  25.  
  26.         throw ExceptionFactory.createException(InvalidConnectionAttributeException.class, 
  27.                 Messages.getString("TimeUtil.UnrecognizedTimezoneId", new Object[] { timezoneStr }), exceptionInterceptor); 
  28.     } 

上述代碼中最終走到了loadTimeZoneMappings(exceptionInterceptor);方法:

  1. private static void loadTimeZoneMappings(ExceptionInterceptor exceptionInterceptor) { 
  2.         timeZoneMappings = new Properties(); 
  3.         try { 
  4.             timeZoneMappings.load(TimeUtil.class.getResourceAsStream(TIME_ZONE_MAPPINGS_RESOURCE)); 
  5.         } catch (IOException e) { 
  6.             throw ExceptionFactory.createException(Messages.getString("TimeUtil.LoadTimeZoneMappingError"), exceptionInterceptor); 
  7.         } 
  8.         // bridge all Time Zone ids known by Java 
  9.         for (String tz : TimeZone.getAvailableIDs()) { 
  10.             if (!timeZoneMappings.containsKey(tz)) { 
  11.                 timeZoneMappings.put(tz, tz); 
  12.             } 
  13.         } 
  14.     } 

該方法加載了配置文件"/com/mysql/cj/util/TimeZoneMapping.properties"里面的值,經(jīng)過轉(zhuǎn)換,timeZoneMappings中,對(duì)應(yīng)CST的為"CST"。

最終得到canonicalTimezone為“CST”,而TimeZone獲得是通過TimeZone.getTimeZone(canonicalTimezone)方法獲得的。

也就是說TimeZone.getTimeZone("CST")的值為美國時(shí)間。寫個(gè)單元測(cè)試驗(yàn)證一下:

  1. public class TimeZoneTest { 
  2.  
  3.  @Test 
  4.  public void testTimeZone(){ 
  5.   System.out.println(TimeZone.getTimeZone("CST")); 
  6.  } 

打印結(jié)果:

  1. sun.util.calendar.ZoneInfo[id="CST",offset=-21600000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=CST,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]] 

很顯然,該方法傳入CST之后,默認(rèn)是美國時(shí)間。

至此,問題原因基本明朗:

  • Mysql中設(shè)置的server_time_zone為CST,time_zone為SYSTEM。
  • Mysql驅(qū)動(dòng)查詢到time_zone為SYSTEM,于是使用server_time_zone的值,為”CST“。
  • JDK中TimeZone.getTimeZone("CST")獲得的值為美國時(shí)區(qū);
  • 以美國時(shí)區(qū)構(gòu)造的Calendar類;
  • SqlTimestampValueFactory使用上述Calendar來格式化系統(tǒng)獲取的中國時(shí)間,時(shí)差問題便出現(xiàn)了;
  • 最終反映在數(shù)據(jù)庫數(shù)據(jù)上就是錯(cuò)誤的時(shí)間。

serverVariables變量

再延伸一下,其中server_time_zone和time_zone都來自于NativeServerSession的serverVariables變量,該變量在NativeSession的loadServerVariables方法中進(jìn)行初始化,關(guān)鍵代碼:

  1. if (versionMeetsMinimum(5, 1, 0)) { 
  2.                 StringBuilder queryBuf = new StringBuilder(versionComment).append("SELECT"); 
  3.                 queryBuf.append("  @@session.auto_increment_increment AS auto_increment_increment"); 
  4.                 queryBuf.append(", @@character_set_client AS character_set_client"); 
  5.                 queryBuf.append(", @@character_set_connection AS character_set_connection"); 
  6.                 queryBuf.append(", @@character_set_results AS character_set_results"); 
  7.                 queryBuf.append(", @@character_set_server AS character_set_server"); 
  8.                 queryBuf.append(", @@collation_server AS collation_server"); 
  9.                 queryBuf.append(", @@collation_connection AS collation_connection"); 
  10.                 queryBuf.append(", @@init_connect AS init_connect"); 
  11.                 queryBuf.append(", @@interactive_timeout AS interactive_timeout"); 
  12.                 if (!versionMeetsMinimum(5, 5, 0)) { 
  13.                     queryBuf.append(", @@language AS language"); 
  14.                 } 
  15.                 queryBuf.append(", @@license AS license"); 
  16.                 queryBuf.append(", @@lower_case_table_names AS lower_case_table_names"); 
  17.                 queryBuf.append(", @@max_allowed_packet AS max_allowed_packet"); 
  18.                 queryBuf.append(", @@net_write_timeout AS net_write_timeout"); 
  19.                 queryBuf.append(", @@performance_schema AS performance_schema"); 
  20.                 if (!versionMeetsMinimum(8, 0, 3)) { 
  21.                     queryBuf.append(", @@query_cache_size AS query_cache_size"); 
  22.                     queryBuf.append(", @@query_cache_type AS query_cache_type"); 
  23.                 } 
  24.                 queryBuf.append(", @@sql_mode AS sql_mode"); 
  25.                 queryBuf.append(", @@system_time_zone AS system_time_zone"); 
  26.                 queryBuf.append(", @@time_zone AS time_zone"); 
  27.                 if (versionMeetsMinimum(8, 0, 3) || (versionMeetsMinimum(5, 7, 20) && !versionMeetsMinimum(8, 0, 0))) { 
  28.                     queryBuf.append(", @@transaction_isolation AS transaction_isolation"); 
  29.                 } else { 
  30.                     queryBuf.append(", @@tx_isolation AS transaction_isolation"); 
  31.                 } 
  32.                 queryBuf.append(", @@wait_timeout AS wait_timeout"); 
  33.  
  34.                 NativePacketPayload resultPacket = sendCommand(this.commandBuilder.buildComQuery(null, queryBuf.toString()), false, 0); 
  35.                 Resultset rs = ((NativeProtocol) this.protocol).readAllResults(-1, false, resultPacket, falsenull
  36.                         new ResultsetFactory(Type.FORWARD_ONLY, null)); 
  37.                 Field[] f = rs.getColumnDefinition().getFields(); 
  38.                 if (f.length > 0) { 
  39.                     ValueFactory<String> vf = new StringValueFactory(this.propertySet); 
  40.                     Row r; 
  41.                     if ((r = rs.getRows().next()) != null) { 
  42.                         for (int i = 0; i < f.length; i++) { 
  43.                             this.protocol.getServerSession().getServerVariables().put(f[i].getColumnLabel(), r.getValue(i, vf)); 
  44.                         } 
  45.                     } 
  46.                 } 

在上述StringBuilder的append操作中,有"@@time_zone AS time_zone"和"@@system_time_zone AS system_time_zone"兩個(gè)值,然后查詢數(shù)據(jù)庫,從數(shù)據(jù)庫獲得值之后,put到serverVariables中。

再來debug一下:

system_time_zone

可以看出system_time_zone的值為CST。

time_zone

同樣time_zone的值為“SYSTEM”。

根據(jù)代碼中的提示,拼接與代碼一樣的SQL查詢一下數(shù)據(jù)庫:

  1. select @@time_zone; 
  2.  
  3. SYSTEM 

值的確是“SYSTEM”。此時(shí),我們又得出另外一個(gè)查詢Mysql當(dāng)前時(shí)區(qū)的方法。

至此,該問題的排查完美收官。大出一口氣。

小結(jié)

在上述問題排查的過程中,多次用到單元測(cè)試,這也是單元測(cè)試的魅力所在,用最簡單的代碼,最輕量的邏輯,最節(jié)省時(shí)間的方式來驗(yàn)證和追蹤錯(cuò)誤。

再回顧一下上述Bug排查中用到和學(xué)到的知識(shí)點(diǎn):

  • Linux日期查看,時(shí)區(qū)查看及衍生如何配置時(shí)區(qū);
  • Mysql時(shí)區(qū)查看;
  • Spring Boot單元測(cè)試;
  • Java時(shí)區(qū)獲取;
  • UTC時(shí)間和CST時(shí)間;
  • 兩種解決時(shí)區(qū)問題的方案;
  • 閱讀、debug Mysql驅(qū)動(dòng)源代碼;
  • TimeZone.getTimeZone("CST")默認(rèn)時(shí)區(qū)為美國時(shí)區(qū);
  • Mysql驅(qū)動(dòng)中處理時(shí)區(qū)問題基本流程邏輯;
  • Mybatis debug日志相關(guān)打印;
  • 其他相關(guān)知識(shí)。 

通過本篇Bug查找的文章,你學(xué)到了什么?如果有那么一點(diǎn)啟發(fā),不要吝嗇,給點(diǎn)個(gè)贊吧!

 

責(zé)任編輯:武曉燕 來源: 程序新視界
相關(guān)推薦

2017-09-12 16:18:22

ICO區(qū)塊鏈互聯(lián)網(wǎng)+

2020-02-20 16:21:46

遠(yuǎn)程辦公

2019-06-03 14:38:11

AWS挖掘機(jī)光纜

2015-12-09 13:51:21

Intelskylake散熱器

2021-04-13 17:38:38

區(qū)塊鏈比特幣安全

2024-08-05 08:00:53

2018-10-19 16:35:20

運(yùn)維

2018-05-02 14:30:33

數(shù)據(jù)庫運(yùn)維優(yōu)化故障

2018-05-08 09:49:15

數(shù)據(jù)庫運(yùn)維優(yōu)化

2019-12-03 13:57:38

CIO背鍋IT

2019-01-16 18:11:28

程序員技能開發(fā)者

2017-08-23 17:11:40

WI-FI流量路由器

2021-04-16 09:20:34

黑客DDoS網(wǎng)絡(luò)攻擊

2023-04-26 07:16:25

游戲掉幀CPU

2019-12-17 10:01:40

開發(fā)技能代碼

2017-06-09 13:36:33

人工智能深度學(xué)習(xí)

2017-09-25 10:52:27

2020-12-09 11:00:44

Nginx 運(yùn)維Tomcat

2021-11-03 16:25:26

Linux磁盤空間命令

2009-07-06 08:36:28

NoSQL關(guān)系數(shù)據(jù)庫
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)