【MySQL】行結構詳解:InnoDb支持格式、如何存儲、頭信息區域、Null列表、變長字段以及與其他格式的對比

📢博客主頁:https://blog.csdn.net/2301_779549673
📢博客倉庫:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
📢本文由 JohnKi 原創,首發于 CSDN🙉
📢未來很長,值得我們全力奔赴更美好的生活?

在這里插入圖片描述

在這里插入圖片描述

文章目錄

  • 🏳??🌈一、InnoDB支持的數據行格式都有哪些?
    • 1.1 如何查看當前數據庫或表應用了哪種行格式?
    • 1.2 如何指定行格式?
    • 1.3 DYNAMIC 格式由哪些部分組成?
  • 🏳??🌈二、數據區是怎么存儲真實數據的?
  • 🏳??🌈三、額外(管理)信息區包含了關于行的哪些信息?
  • 🏳??🌈四、頭信息區域包含了哪些信息?
    • 4.1 刪除一行記錄時在InnoDB內部執行了哪些操作?
  • 🏳??🌈五、NuIl列表有啥作用? 列表中的值是什么?
  • 🏳??🌈六、變長字段列表有啥作用?列表中的值是什么?
    • 6.1 如何記錄變長字段的實際長度?
    • 6.2 讀取長度時如何處理粘包問題?
  • 🏳??🌈七、其他的行格式與 DYNAMIC 有什么區別?
    • 7.1 REDUNDANT 冗余格式
    • 7.2 COMPRESSED 壓縮格式
    • 7.3 COMPACT 緊湊格式
  • 👥總結


真實的數據在表空間以數據行的形式存儲,也就是說每一條數據都對應著表中的一行,數據行在頁中的位置如下圖所示:

在這里插入圖片描述

🏳??🌈一、InnoDB支持的數據行格式都有哪些?

InnoDB 支持四種行格式,分別是: REDUNDANT 冗余格式COMPACT 緊湊格式DYNAMIC 動態格式COMPRESSED 壓縮格式

默認是 DYNAMIC 格式。

1.1 如何查看當前數據庫或表應用了哪種行格式?

# 查看系統變量中設置的?格式
mysql> SHOW VARIABLES LIKE 'innodb_default_row_format';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
1 row in set (0.00 sec)
# 使?SHOW table STATUS查看數據庫中的所有表
mysql> SHOW TABLE STATUS IN test_db\G
*************************** 1. row ***************************Name: classesEngine: InnoDBVersion: 10Row_format: Dynamic				# 指定數據庫使?的?格式Rows: 3Avg_row_length: 5461Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 4Create_time: 2025-05-02 19:14:14Update_time: NULLCheck_time: NULLCollation: utf8mb4_general_ciChecksum: NULLCreate_options: row_format=DYNAMICComment: 
*************************** 2. row ***************************Name: courseEngine: InnoDBVersion: 10Row_format: DynamicRows: 6Avg_row_length: 2730Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 7Create_time: 2025-05-02 19:14:14Update_time: NULLCheck_time: NULLCollation: utf8mb4_general_ciChecksum: NULLCreate_options: row_format=DYNAMICComment: 
*************************** 3. row ***************************Name: scoreEngine: InnoDBVersion: 10Row_format: DynamicRows: 15Avg_row_length: 1092Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: NULLCreate_time: 2025-05-02 19:14:14Update_time: NULLCheck_time: NULLCollation: utf8mb4_general_ciChecksum: NULLCreate_options: row_format=DYNAMICComment: 
# ... 省略
16 rows in set (0.06 sec)

1.2 如何指定行格式?

  • 可以通過 全局變量 設置行格式
  • 也可以在創建表中通過 ROW_FORMAT 子句指定行格式:
# 通過全局變量設置
SET GLOBAL innodb_default_row_format=DYNAMIC;# 在創建表時明確的指定?格式
CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;

1.3 DYNAMIC 格式由哪些部分組成?

一個 DYNAMIC 格式的數據行會被分為兩部分

  • 一部分是存儲 真實數據 的區域
  • 一部分是存儲 額外信息 的區域

在頁結構的小節已經對行做了簡單介紹,下面來詳細講解一下行的組成結構

🏳??🌈二、數據區是怎么存儲真實數據的?

數據區在數據行中的位置如下圖所示:
在這里插入圖片描述

從分隔線向右第一個字段存儲真實數據的主鍵值,對于 主鍵值 有以下幾種情況:

  • 如果表中定義了主鍵,則直接存儲 主鍵 的值;。
  • 如果是復合主鍵根據列定義的順序 依次排列在這里;
  • 如果沒有主鍵,會優先使用 第一個不允許為 NULL 的 UNIQUE 唯一列 作為主鍵;
  • 如果既沒有主鍵也沒有唯一鍵,那么InnoDB會構建一個6字節的字段 DB_ROW_ID 作為行的唯一標識,存儲在真實數據的頭部

緊接著是在事務運行中兩個非常重要的固定字段

  • 6字節的事務ID字段 DB_TXID,記錄創建或最后一次修改該記錄的事務ID
  • 7字節的回滾指針字段 DB_ROLL_PTR,如果在事務中這條記錄被修改,指向這條記錄的上一個版本

接下來就是除了 主鍵值為NULL 的列之外,其他列的真實數據,按照順序從左到右依次排列

至于為什么不存儲NULL值,原因很簡單,就是為了節少空間,所有允許為NULL的列都會在行額外信息區的NULL值列表中進行標識 ,后面我們會詳細詳解,以上就是數據行對真實數據的存儲方式。

在這里插入圖片描述

🏳??🌈三、額外(管理)信息區包含了關于行的哪些信息?

在這里插入圖片描述
額外信息區從右向左分別為: 頭信息NuI值列表變長字段列表

🏳??🌈四、頭信息區域包含了哪些信息?

在這里插入圖片描述

  • 下一行地址偏移量: next_record 占16bit,通過這個信息將所有的行鏈接成一個單向鏈表
  • 行類型: record_type 占3bit,包括四種類型:
    • 0: 普通數據行
    • 1: 索引目錄行
    • 2: 頁內最小行 infimun
    • 3: 頁內最大行 supremun
  • 行在整個頁中的位置: heap_no 占13bit;
  • 分組的行數: n_owned 占4bit,只在該行是分組最后一行才有值,這樣就可以快速查詢行數,而不用一條條的累加了
  • B+樹索引樹每層最小值標記: min_rec_flag 占lbit,如果當前行的類型是目錄行也就是 record_type=1,同時也是B+索引樹某層的最小值,則會置為1,會在索引查詢時用到,后面我們講索引時再介紹
  • 刪除標記: delete_mask1bit,從頁中刪除數據行時,并不會直接移除,而是修改這個刪除標記為
  • 預留區: 占2bit

4.1 刪除一行記錄時在InnoDB內部執行了哪些操作?

從頁中刪除數據行時,并不會直接移除,而是修改 delete_mask 這個刪除標記為1,并將 next_record 改為0,同時將 上一行的 next_record 指向后續的行,從而把該行從鏈表中斷開

如果執行事務提交后,則這行的 next_record 指向一個被稱為垃圾鏈表的區域,這個鏈表會被用在事務回滾中,后續在事務中詳細介紹

🏳??🌈五、NuIl列表有啥作用? 列表中的值是什么?

  • 頭信息區再向右就是 NULL值列表的可變區域,用來存儲數據行中所有列允許為Null的值從而節省空間,具體的實現方式是,用1BIT的大小來表示行中某一列是否為空,這樣空列就不需要記錄在真實數據區域中了
  • 為每個沒有定義 NOT NULL 約束也就是可以為NULL的列在NULL值列表中都安排了一個bit位,按列序號從小到大的順序從右至左依序安排,這就是常說的逆序排列,NULL值列表最小1字節即8bit,如果沒有那么多可以為NULL的列,則會用0補滿8bit,如果為值為NULL的列超過8個,則新開辟1字節的空間,依此類推:
  • 如果某列為空,則NULL值列表中對應的bit設置為1,這樣只用了一bit就存儲了NULL列,非常節省空間

在這里插入圖片描述

🏳??🌈六、變長字段列表有啥作用?列表中的值是什么?

查看編碼集所占的字節數

mysql> show charset;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| utf8mb3  | UTF-8 Unicode                   | utf8mb3_general_ci  |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

在這里插入圖片描述

以下是?個建表的SQL語句

mysql> CREATE TABLE test_student (-> `id` bigint NOT NULL AUTO_INCREMENT,-> `sn` char(10) NOT NULL,-> `name` varchar(50) NOT NULL,-> `age` int NOT NULL,-> `mail` varchar(100) NOT NULL,-> `remark` varchar(255) NULL,-> PRIMARY KEY (`id`)-> );
Query OK, 0 rows affected (0.09 sec)
  • 行結構的最左側是變長字段列表,也叫可變字段長度列表,在這個列表中記錄了數據行中所有變長字段的實際長度,這樣做的目的,是為了在真實數據區域,可以根據列的長度進行列與列之間的分割;
  • 需要記錄的變長字段類型常見的有varchar、varbinary、text、blob,以及當使用了例如utf-8、gbk等變長字符集的char類型,當char類型的字節數可能超過768個字節時,比如使用utf8mb4字符集時定義了char(255),這個字段的最大字節數是4*255=1020
  • 每個變長字段分配1~2個字節來存放這些字段的真實大小,放置順序也是按表中字段的順序從右至左逆序排列;
mysql> CREATE TABLE test_varchar (-> `id` bigint NOT NULL AUTO_INCREMENT,-> `name` varchar(20000) NULL,-> PRIMARY KEY (`id`)-> );
ERROR 1074 (42000): Column length too big for column 'name' (max = 16383); use BLOB or TEXT instead
  • 2個字節最大可以表示65535個字節,按照最大長度字符串,比如 utf8mb4,一個字符占用最多4個字節計算,2個字節最多可以表示65535/4=16383個字符,列數據類型varchar的長度上限16383就是根據這個計算來的;
  • 需要特別說明的是,如果text、blob存儲的內容過大,一個頁已經不夠放了,就會把這個列放入一個叫"溢出頁"的獨立空間中,在這個數據行對應的真實數據處,只使用20個字節來標記這個溢出頁的位置信息

在這里插入圖片描述

6.1 如何記錄變長字段的實際長度?

不同的字符集在處理字符對應的最大字節長度不同,以如 ascii 最大1個字節, utf8mb3 最大3個字節,utf8mb4 最大4個字節,如下所示

| ascii   | US ASCII 	  | ascii_general_ci   | 1 |
| utf8mb3 | UTF-8 Unicode | utf8mb3_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |

當使用 varchar(M ) 指定一個字段的最大字符數時,該字段真實使用的字節數與建表時指定的字符集有關,如果指定的字符集單個字符最大占 w個字節,從理論上講,該列最多使用的字節數 M *如果 M *W<= 255 則用一個字節記錄這個變長字段的長度就足夠了

如果 M *W> 255 可能分為兩種情況,假設當前變長字段實現占用了L個字節:

6.2 讀取長度時如何處理粘包問題?

  • 也就是說在讀取變長字段長度時,如何確定讀取一個字節還是兩個字節?
  • 在任何時候都是先讀一個字節,然后判斷這個字節的高位是否為0,如果是0則表示當前用一個字節表示長度,如果是1則表示當前用兩個字節表示長度
  • 為1時再讀一個字節,然后合并在一起進行解析得到該字段真實的使用的字節數,而且第二個BIT位表示是否使用溢出頁

默認數據頁大小為16KB,數據頁中一個數據行的大小最大為8KB

在這里插入圖片描述

🏳??🌈七、其他的行格式與 DYNAMIC 有什么區別?

7.1 REDUNDANT 冗余格式

已被淘汰,之所以存在是為了與舊版本 MySQL兼容,不建議使用,這里不再討論。

7.2 COMPRESSED 壓縮格式

行結構與 DYNAMIC 完全相同,只是會對數據進行壓縮,以減少對空間的占用。

7.3 COMPACT 緊湊格式

在結構上與 DYNAMIC 相同,只是對超長字段的處理上有些區別,它不會把所有超長數據都放在溢出頁中,而是會在本行中保留前768個字節的數據,多出的部分放在溢出頁中,溢出頁的地址額外用20個字節表示,那么在本行的列中就會占用768+20個字節。


👥總結

在這里插入圖片描述

本篇博文對 【MySQL】行結構詳解:InnoDb支持格式、如何存儲、頭信息區域、Null列表、變長字段以及與其他格式的對比 做了一個較為詳細的介紹,不知道對你有沒有幫助呢

覺得博主寫得還不錯的三連支持下吧!會繼續努力的~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82583.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82583.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82583.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LabVIEW多通道并行數據存儲系統

在工業自動化監測、航空航天測試、生物醫學信號采集等領域&#xff0c;常常需要對多個傳感器通道的數據進行同步采集&#xff0c;并根據后續分析需求以不同采樣率保存特定通道組合。傳統單線程數據存儲方案難以滿足實時性和資源利用效率的要求&#xff0c;因此設計一個高效的多…

【Linux系列】bash_profile 與 zshrc 的編輯與加載

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

針對Mkdocs部署到Githubpages加速訪問速度的一些心得

加速網站訪問的一些心得 在使用 MkDocs 構建網站時&#xff0c;為了提高訪問速度&#xff0c;我們可以采取以下一些措施&#xff1a; 1. 優化圖片 使用合適的圖片格式&#xff0c;如 WebP、JPEG2000 等&#xff0c;減少圖片文件大小&#xff0c;從而加快加載速度。 可以使用…

Mysql中切割字符串作為in的查詢條件

問題&#xff1a;需要將一個字符串切割成數組作為in的查詢條件&#xff0c;如&#xff1a; select * from table_1 where name in (select slit(names) from table_2 where id 3); names 返回的格式是’name1,name2,name3…,需要將name按照逗號切割作為in的查詢條件&#xff1b…

云計算中的虛擬化:成本節省、可擴展性與災難恢復的完美結合

云計算中虛擬化的 4 大優勢 1. 成本效益 從本質上講&#xff0c;虛擬化最大限度地減少了硬件蔓延。團隊可以將多個虛擬機整合到單個物理主機上&#xff0c;而不是為每個工作負載部署單獨的服務器。這大大減少了前期硬件投資和持續維護。 結果如何&#xff1f;更低的功耗、更低…

Linux : 多線程【線程概念】

Linux &#xff1a; 多線程【線程概念】 &#xff08;一&#xff09;線程概念線程是什么用戶層的線程linux中PID與LWP的關系 (二) 進程地址空間頁表(三) 線程總結線程的優點線程的缺點線程異常線程用途 &#xff08;一&#xff09;線程概念 線程是什么 在一個程序里的一個執行…

IDEA轉戰TREA AI IDE : springboot+maven+vue項目配置

一、trea下載安裝 Trae官方網址&#xff1a; https://www.trae.com.cn/ Trae官方文檔&#xff1a;https://docs.trae.com.cn/docs/what-is-trae?_langzh w3cschool&#xff1a; https://www.w3cschool.cn/traedocs/ai-settings.html 安裝這里省略&#xff0c;正常安裝即可。…

Java--圖書管理系統(簡易版)

目錄 目錄 前言 &#x1f514;1.library包 1.1 Book類 1.2 BookList類 &#x1f514;2.user包 2.1User類(父類) 2.2Admin(管理員) 2.3 NormalUser(普通用戶) &#x1f514;3.Operation包 &#x1f550;3.1 IOperation接口 &#x1f551;3.2ListOperation(查看操作)…

深入淺出:Spring Boot 中 RestTemplate 的完整使用指南

在分布式系統開發中&#xff0c;服務間通信是常見需求。作為 Spring 框架的重要組件&#xff0c;RestTemplate 為開發者提供了簡潔優雅的 HTTP 客戶端解決方案。本文將從零開始講解 RestTemplate 的核心用法&#xff0c;并附贈真實地圖 API 對接案例。 一、環境準備 在 Spring…

大數據處理利器:Hadoop 入門指南

一、Hadoop 是什么&#xff1f;—— 分布式計算的基石 在大數據時代&#xff0c;處理海量數據需要強大的技術支撐&#xff0c;Hadoop 應運而生。Apache Hadoop 是一個開源的分布式計算框架&#xff0c;致力于為大規模數據集提供可靠、可擴展的分布式處理能力。其核心設計理念是…

685SJBH計量管理系統

摘 要 計量&#xff0c;在我國已有五千年的歷史。計量的發展與社會進步聯系在一起&#xff0c;它是人類文明的重要組成部分。它的發展經歷了古典階段、經典階段和現代階段。而企業的計量管理是對測量數據、測量過程和測量設備的管理。 本系統通過分析現有計量系統的業務邏輯…

從0到1構建前端監控系統:錯誤捕獲、性能采集、用戶體驗全鏈路追蹤實戰指南SDK實現

目錄 前言為什么要做前端監控前端監控目標穩定性用戶體驗業務 前端監控流程常見埋點方案代碼埋點可視化埋點無痕埋點 創建項目第一步、創建monitor文件&#xff0c;cmd進入文件進行npm init -y 項目初始化第二步、創建src/index.js和src/index.html文件第三步、創建webpack.con…

前端瀏覽器判斷設備類型的方法

前端瀏覽器判斷設備類型的方法 在前端開發中&#xff0c;判斷設備類型&#xff08;如手機、平板、桌面電腦&#xff09;有多種方法&#xff0c;以下是常用的幾種方式&#xff1a; 1. 使用 User Agent 檢測 通過 navigator.userAgent 獲取用戶代理字符串進行判斷&#xff1a;…

MNIST 手寫數字分類

轉自我的個人博客: https://shar-pen.github.io/2025/05/04/torch-distributed-series/1.MNIST/ 基礎的單卡訓練 本筆記本演示了訓練一個卷積神經網絡&#xff08;CNN&#xff09;來對 MNIST 數據集中的手寫數字進行分類的過程。工作流程包括&#xff1a; 數據準備&#xff…

數據庫中的 Segment、Extent、Page、Row 詳解

在關系型數據庫的底層存儲架構中&#xff0c;數據并不是隨意寫入磁盤&#xff0c;而是按照一定的結構分層管理的。理解這些存儲單位對于優化數據庫性能、理解 SQL 執行過程以及排查性能問題都具有重要意義。 我將從宏觀到微觀&#xff0c;依次介紹數據庫存儲中的四個核心概念&…

DAMA車輪圖

DAMA車輪圖是國際數據管理協會&#xff08;DAMA International&#xff09;提出的數據管理知識體系&#xff08;DMBOK&#xff09;的圖形化表示&#xff0c;它以車輪&#xff08;同心圓&#xff09;的形式展示了數據管理的核心領域及其相互關系。以下是基于用戶提供的關鍵詞對D…

《QDebug 2025年4月》

一、Qt Widgets 問題交流 1. 二、Qt Quick 問題交流 1.QML單例動態創建的對象&#xff0c;訪問外部id提示undefined 先定義一個窗口組件&#xff0c;打印外部的id&#xff1a; // MyWindow.qml import QtQuick 2.15 import QtQuick.Window 2.15Window {id: controlwidth: …

JS | 正則 · 常用正則表達式速查表

以下是前端開發中常用的正則表達式速查表&#xff0c;包含驗證規則、用途說明與示例&#xff1a; &#x1f4cc; 常用正則表達式速查表 名稱正則表達式描述 / 用途示例手機號/^1[3-9]\d{9}$/中國大陸手機號13812345678 ?座機號/^0\d{2,3}-?\d{7,8}$/固定電話010-12345678 ?…

系統思考:個人與團隊成長

四年前&#xff0c;我交付的系統思考項目&#xff0c;今天學員的反饋依然深深觸動了我。 我常常感嘆&#xff0c;系統思考不僅僅是一場培訓&#xff0c;更像是一場持續的“修煉”。在這條修煉之路上&#xff0c;最珍貴的&#xff0c;便是有志同道合的伙伴們一路同行&#xff0…