日誌:Redo Log 和 Undo Log

来源:https://www.cnblogs.com/feiyu2/archive/2022/09/09/16672433.html
-Advertisement-
Play Games

本篇文章主要介紹 Redo Log 和 Undo Log: 1. 利用 Redo Log 和 Undo Log 實現本地事務的原子性、持久性 2. Redo Log 的寫回策略 3. Redo Log Buffer 的刷盤時機 ...


本篇文章主要介紹 Redo Log 和 Undo Log:

  1. 利用 Redo Log 和 Undo Log 實現本地事務的原子性、持久性
  2. Redo Log 的寫回策略
  3. Redo Log Buffer 的刷盤時機

日誌:Redo Log 和 Undo Log · 語雀 (yuque.com)

通過寫入日誌來保證原子性、持久性是業界的主流做法。

介紹 Redo Log 和 Undo Log

Redo Log 是什麼:Redo Log 被稱為重做日誌。

Undo Log 是什麼:Undo Log 被稱為撤銷日誌、回滾日誌。

技術是為瞭解決問題而生的,通過 Redo Log 我們可以實現崩潰恢復,防止數據更新丟失,保證事務的持久性。也就是說,在機器故障恢復後,系統仍然能夠通過 Redo Log 中的信息,持久化已經提交的事務的操作結果。

技術是為瞭解決問題而生的,Undo Log 的作用 / 功能:

  • 事務回滾:可以對提前寫入的數據變動進行擦除,實現事務回滾,保證事務的原子性。
  • 實現 MVCC 機制:Undo Log 也用於實現 MVCC 機制,存儲記錄的多個版本的 Undo Log,形成版本鏈。

Undo Log 中存儲了回滾需要的數據。在事務回滾或者崩潰恢復時,根據 Undo Log 中的信息對提前寫入的數據變動進行擦除。


Redo Log 和 Undo Log 都是用於實現事務的特性,並且都是在存儲引擎層實現的。由於只有 InnoDB 存儲引擎支持事務,因此只有使用 InnoDB 存儲引擎的表才會使用 Redo Log 和 Undo Log。

實現本地事務的原子性、持久性

“Write-Ahead Log”日誌方案

MySQL 的 InnoDB 存儲引擎使用“Write-Ahead Log”日誌方案實現本地事務的原子性、持久性。

“提前寫入”(Write-Ahead),就是在事務提交之前,允許將變動數據寫入磁碟。與“提前寫入”相反的就是,在事務提交之前,不允許將變動數據寫入磁碟,而是等到事務提交之後再寫入。

“提前寫入”的好處是:有利於利用空閑 I/O 資源。但“提前寫入”同時也引入了新的問題:在事務提交之前就有部分變動數據被寫入磁碟,那麼如果事務要回滾,或者發生了崩潰,這些提前寫入的變動數據就都成了錯誤。“Write-Ahead Log”日誌方案給出的解決辦法是:增加了一種被稱為 Undo Log 的日誌,用於進行事務回滾。

變動數據寫入磁碟前,必須先記錄 Undo Log,Undo Log 中存儲了回滾需要的數據。在事務回滾或者崩潰恢復時,根據 Undo Log 中的信息對提前寫入的數據變動進行擦除。


“Write-Ahead Log”在崩潰恢復時,會經歷以下三個階段:

  • 分析階段(Analysis):該階段從最後一次檢查點(Checkpoint,可理解為在這個點之前所有應該持久化的變動都已安全落盤)開始掃描日誌,找出所有沒有 End Record 的事務,組成待恢復的事務集合(一般包括 Transaction Table 和 Dirty Page Table)。
  • 重做階段(Redo):該階段依據分析階段中,產生的待恢復的事務集合來重演歷史(Repeat History),找出所有包含 Commit Record 的日誌,將它們寫入磁碟,寫入完成後增加一條 End Record,然後移除出待恢復事務集合。
  • 回滾階段(Undo):該階段處理經過分析、重做階段後剩餘的待恢復事務集合,此時剩下的都是需要回滾的事務(被稱為 Loser),根據 Undo Log 中的信息回滾這些事務。

MySQL 中一條 SQL 更新語句的執行過程

以下的執行過程限定在,使用 InnoDB 存儲引擎的表

  1. 事務開始

  2. 申請加鎖:表鎖、MDL 鎖、行鎖、索引區間鎖(看情況加哪幾種鎖)

  3. 執行器找存儲引擎取數據。

    1. 如果記錄所在的數據頁本來就在記憶體(innodb_buffer_cache)中,存儲引擎就直接返回給執行器;
    2. 否則,存儲引擎需要先將該數據頁從磁碟讀取到記憶體,然後再返回給執行器。
  4. 執行器拿到存儲引擎給的行數據,進行更新操作後,再調用存儲引擎介面寫入這行新數據。

  5. 存儲引擎將回滾需要的數據記錄到 Undo Log,並將這個更新操作記錄到 Redo Log,此時 Redo Log 處於 prepare 狀態。並將這行新數據更新到記憶體(innodb_buffer_cache)中。同時,然後告知執行器執行完成了,隨時可以提交事務。

  6. 手動事務 commit:執行器生成這個操作的 Binary Log,並把 Binary Log 寫入磁碟。

  7. 執行器調用存儲引擎的提交事務介面,存儲引擎把剛剛寫入的 Redo Log 改成 commit 狀態。

  8. 事務結束

其中第 5 步,將這個更新操作記錄到 Redo Log。生成的 Redo Log 是存儲在 Redo Log Buffer 後就返回,還是必須寫入磁碟後才能返回呢?

這就是 Redo Log 的寫入策略,Redo Log 的寫入策略由 innodb_flush_log_at_trx_commit 參數控制,該參數不同的值對應不同的寫入策略。

還有第 6 步,把 Binary Log 寫入磁碟和 Redo Log 一樣,也有相應的寫回策略,由參數 sync_binlog 控制。

通常我們說 MySQL 的“雙 1”配置,指的就是 sync_binlog 和 innodb_flush_log_at_trx_commit 都設置成 1。也就是說,一個事務提交前,需要等待兩次刷盤,一次是 Redo Log 刷盤(prepare 階段),一次是 Binary Log 刷盤。

Redo Log 的兩階段提交 & 崩潰恢復

在上面【MySQL 中一條 SQL 更新語句的執行過程】部分,最後將 Redo Log 的寫入拆成了兩個步驟:prepare 和 commit,這就是"兩階段提交"。

“兩階段提交”的作用 / 目的:

  • 將事務設置為 prepare,為了在崩潰重啟時,能夠知道事務的狀態
  • 保證兩份日誌(Binary Log 和 Redo Log)之間的邏輯一致。

如果先寫 Redo Log,再寫 Binary Log 或者 先寫 Binary Log,再寫 Redo Log,寫入第一個日誌後,如果此時發生了崩潰,那麼第二個日誌沒有寫入,就造成了兩個日誌的不一致。資料庫的狀態就有可能和用 Binary Log 恢復出來的庫的狀態不一致。備庫利用 Binary Log 進行數據同步,就會出現主備庫數據不一致的問題。具體的講解可以看極客時間的專欄《MySQL實戰45講》

file

而使用“兩階段提交”,遵守“崩潰恢復時,判斷事務該提交、還是該回滾的規則”,就可以保證兩份日誌(Binary Log 和 Redo Log)之間的邏輯一致。

“崩潰恢復時,判斷事務該提交、還是該回滾的規則”如下:

  1. 如果 Redo Log 裡面的事務是完整的,也就是已經有了 commit 標識,那麼利用該 Redo Log 中的信息,持久化事務的操作結果;
  2. 如果 Redo Log 裡面的事務只有完整的 prepare,則判斷對應事務的 Binary Log 是否存在並完整:
    a. 如果是,利用該 Redo Log 中的信息,持久化事務的操作結果;
    b. 如果否,則回滾事務,根據 Undo Log 中的信息對提前寫入的數據變動進行擦除。

如果事務寫入 Redo Log 處於 prepare 階段之後、寫 Binary Log 之前,發生了崩潰(也就是時刻 A 發生了崩潰),由於此時 Binary Log 還沒寫,Redo Log 也還沒處於 commit 狀態,所以崩潰恢復的時候,這個事務會回滾。這時 Binary Log 還沒寫,所以也不會傳到備庫。主庫和備庫的數據狀態一致。

如果事務寫入 Binary Log 之後,Redo Log 還沒處於 commit 狀態之前,發生了崩潰(也就是時刻 B 發生了崩潰),根據崩潰恢復時的判斷規則中第 2 條,Redo Log 處於 prepare 階段,Binary Log 完整,所以崩潰恢復的時候,會利用該 Redo Log 中的信息,持久化事務的操作結果。這時 Binary Log 已經寫了,所以會傳到備庫。主庫和備庫的數據狀態一致。


Binary Log 的寫入在崩潰恢復時,判斷事務該提交還是該回滾時,起到了至關重要的作用,只有 Binary Log 寫入成功才能保證兩份日誌(Binary Log 和 Redo Log)之間的邏輯一致,才能考慮提交。

Redo Log 配置的選項

  • innodb_log_buffer_size:Redo Log Buffer 的記憶體大小
  • innodb_log_file_size:單個 Redo Log 文件的空間大小
  • innodb_log_files_in_group:Redo Log 文件的數量(預設值是 2)
  • innodb_log_group_home_dir:Redo Log 文件的存儲目錄(預設值是 .\ ,即數據目錄)
  • innodb_flush_log_at_trx_commit:Redo Log 的寫入策略

Redo Log 的寫入策略

我們在【MySQL 中一條 SQL 更新語句的執行過程】部分的第 5 步中說:存儲引擎將這行新數據更新到記憶體(innodb_buffer_cache)中。同時,將這個更新操作記錄到 Redo Log,此時 Redo Log 處於 prepare 狀態。然後告知執行器執行完成了,隨時可以提交事務。

生成的 Redo Log 是存儲在 Redo Log Buffer 後就返回,還是必須寫入磁碟後才能返回呢?這就是 Redo Log 的寫入策略。Redo Log 的寫入策略由 innodb_flush_log_at_trx_commit 參數控制。

我們可以通過修改該參數的值,設置 Redo Log 的寫入策略,該參數可選的值有 3 個:

  • 值為 0 :表示每次事務提交時,只是把 Redo Log 存儲到記憶體(Redo Log Buffer)就返回,不關心寫入文件
  • 值為 1 :表示每次事務提交時,將 Redo Log Buffer 中的內容寫入並同步到文件後才能返回(write + fsync 才能返回,這是參數的預設值)
  • 值為 2 :表示每次事務提交時,只是把 Redo Log Buffer 中的內容寫入內核緩衝區,但不對文件進行同步,何時同步由操作系統來決定(write,fsync 的時機由操作系統決定)

Redo Log 文件組

MySQL 的數據目錄(使用 show variables like 'datadir' 查看)下預設有兩個名為 ib_logfile0 和

ib_logfile1 的文件,Redo Log Buffer 中的 Redo Log 預設情況下就是刷新到這兩個磁碟文件中。

數據目錄的位置也可以通過以下命令查看:select @@datadir;

file
file


如果我們對預設的 Redo Log 文件組不滿意,可以通過下邊幾個啟動參數來調節:

  • innodb_log_buffer_size:每個 Redo Log 文件的空間大小
  • innodb_log_file_size:每個 Redo Log 文件的最大空間大小
  • innodb_log_files_in_group:Redo Log 文件組中所有 Redo Log 文件的數量(預設值是 2,最大值是 100)
  • innodb_log_group_home_dir:Redo Log 文件的存儲目錄(預設值是 .\ ,即 MySQL 的數據目錄)

從上邊的描述中可以看到,磁碟上的 Redo Log 文件不只一個,而是以一個 日誌文件組 的形式出現的。這些文件

以 ib_logfile[數字] ( 數字 可以是 0 、 1 、 2 ...)的形式進行命名。

在將 Redo Log 寫入 日誌文件組 時,是從 ib_logfile0 開始寫,如果 ib_logfile0 寫滿了,就接著 ib_logfile1 寫,同理, ib_logfile1 寫滿了就去寫 ib_logfile2 ,依此類推。

如果寫到最後一個文件該怎麼辦呢?那就重新轉到 ib_logfile0 繼續寫,所以整個過程如下圖所示:

file

總共的 Redo Log 文件空間大小其實就是:innodb_log_file_size × innodb_log_files_in_group 。(單個文件的空間大小 * 文件組中的文件個數)

如果採用迴圈使用的方式向 Redo Log 文件組裡寫數據的話,那就會造成追尾,也就是後寫入的 Redo Log 覆蓋掉前邊寫的 Redo Log。為瞭解決 Redo Log 的覆蓋寫入問題,InnoDB 的設計者提出了 checkpoint 的概念。

Redo Log 寫入 Redo Log Buffer

Redo Log 的格式

InnoDB 的設計者為 Redo Log 定義了多種類型,以應對事務對資料庫的不同修改場景,但是絕大部分類型的 Redo Log 都有下邊這種通用的結構:

file

各個部分的詳細釋義如下:

  • type:該條 Redo Log 的類型
  • space ID :表空間ID
  • page number :頁號
  • data :該條 Redo Log 的具體內容

在 MySQL 5.7.21 這個版本中,InnoDB 的設計者一共為 Redo Log 設計了 53 種不同的類型。各種類型的 Redo Log 的不同之處在於 data 的具體結構不同。

Redo Log 的具體格式可以看掘金小冊《MySQL 是怎樣運行的:從根兒上理解 MySQL》

這些類型的 Redo Log 既包含 物理 層面的意思,也包含 邏輯 層面的意思,具體指:

  • 物理層面看,這些日誌都指明瞭對哪個表空間的哪個頁進行了什麼修改。
  • 邏輯層面看,在系統奔潰重啟時,並不能直接根據 Redo Log 中的信息,將頁面內的某個偏移量處恢覆成某個數據,而是需要調用一些事先準備好的函數,執行完這些函數後才可以將頁面恢覆成系統奔潰前的樣子。

總結來說,Redo Log 中記錄的是該操作對哪個表空間的哪個頁的哪個偏移量進行了什麼修改。

Mini-Transaction

一個事務可能包含多條 SQL 語句,每一條 SQL 語句可能包含多個「對底層頁面的操作」,每個「對底層頁面的操作」可能包含多個 Redo Log。這樣的一個「對底層頁面的操作」的過程被稱為 Mini-Transaction,簡稱 mtr。

「對底層頁面的操作」比如說:

  • 向聚簇索引對應的 B+ 樹的某個頁面中插入一條記錄,插入一條記錄這個操作可能包含多個 Redo Log

我們需要保證一個「對底層頁面的操作」對應的多個 Redo Log 不可分割,即一個「對底層頁面的操作」是原子的,這個操作對應的 Redo Log 要麼都寫入磁碟,要麼都不寫入磁碟。所以 InnoDB 的設計者規定在執行這些需要保證原子性的操作時必須以 組 的形式來記錄 Redo Log,在進行奔潰恢復時,針對某個組中的 Redo Log,要麼把全部的 Redo Log 都恢復掉,要麼一個 Redo Log 也不恢復。

那麼 InnoDB 的設計者是怎麼做到分組的呢?InnoDB 的設計者在一個「對底層頁面的操作」的最後一個 Redo Log 後面加上一個特殊類型的 Redo Log。相當於某個需要保證原子性的操作產生的一系列 Redo Log 必須要以一個特殊類型的 Redo Log 結尾,這樣在奔潰恢復時:

  • 只有當解析到特殊類型的 Redo Log 時,才認為解析到了一組完整的 Redo Log,才會進行恢復。
  • 否則的話直接放棄前邊解析到的 Redo Log。

file

Redo Log Buffer

Redo Log Buffer 就是在伺服器啟動時,向操作系統申請的大一片連續的記憶體空間。

這片連續的記憶體空間被劃分為若幹個連續的用來存儲 Redo Log 的數據頁。

用來存儲 Redo Log 的數據頁被稱為 Redo Log Block。

我們可以通過啟動參數 innodb_log_buffer_size 來指定 Redo Log Buffer 的大小。

file

file

  • LOG_BLOCK_CHECKPOINT_NO :表示 checkpoint 的序號

file

Redo Log 寫入 Redo Log Buffer

我們前邊說過一個 mtr 執行過程中可能產生若幹個 Redo Log ,這些 Redo Log 是一個不可分割的組,所以其實並不是每生成一個 Redo Log,就將其插入到 Redo Log Buffer 中,而是每個 mtr 運行過程中產生的日誌先暫時存到一個地方,當該 mtr 結束的時候,將過程中產生的一組 Redo Log 再全部複製到 Redo Log Buffer 中。

不同的事務可能是併發執行的,所以不同事務的 mtr 可能是交替執行的。每當一個 mtr 執行完成時,伴隨

該 mtr 生成的一組 Redo Log 就需要被覆制到 Redo Log Buffer 中,也就是說不同事務的 mtr 可能是交替寫入 Redo Log Buffer 的。

Redo Log Buffer 中 Redo Log 的刷盤時機

mtr 運行過程中產生的一組 Redo Log 在 mtr 結束時會被覆制到 Redo Log Buffer 中,在一些情況下 Redo Log Buffer 中的 Redo Log 會被寫回磁碟,Redo Log 的刷盤時機如下:

  • Redo Log Buffer 的空間不足時,執行刷盤操作
  • 一個事務提交時,執行刷盤操作(需要設置指定參數)
  • 將某個臟頁刷新到磁碟前,會先保證該臟頁對應的 Redo Log 刷新到磁碟中(Redo Log 是順序寫入的,因此在將某個臟頁對應的 Redo Log 從 Redo Log Buffer 刷新到磁碟時,也會保證將在其之前產生的 Redo Log 也刷新到磁碟中。
  • 後臺線程不停的執行刷盤操作
  • 正常關閉伺服器時,執行刷盤操作
  • 做 checkpoint 時,執行刷盤操作

Redo Log Buffer 的空間不足時,執行刷盤操作

Redo Log Buffer 的空間是有限的,空間大小由 innodb_log_buffer_size 來指定。

InnoDB 的設計者認為:如果 Redo Log Buffer 的記憶體被占用 1 / 2,就需要把 Redo Log Buffer 中的 Redo Log 刷新到磁碟。


一個事務提交時,執行刷盤操作

在前面【Redo Log 的寫入策略】部分,講到我們可以通過設置 innodb_flush_log_at_trx_commit 參數的值,在事務提交時執行刷盤操作後才能返回。

事務提交時執行刷盤操作後才能返回是 Redo Log 的預設寫入策略。


後臺線程不停的執行刷盤操作

後臺有一個線程,每秒都會執行一次刷盤操作。後臺線程執行刷盤操作的頻率可以通過參數設置。

具體通過哪個參數設置,我也不清楚。


正常關閉伺服器時,執行刷盤操作


做 checkpoint 時,執行刷盤操作


等等

Undo Log 的寫回策略

MySQL中的 Undo Log 嚴格的講不是 Log,而是數據,因此它的管理和落盤都跟數據是一樣的:

  • Undo 的磁碟結構並不是順序的,而是像數據一樣按 Page 管理
  • Undo 寫入時,也像數據一樣產生對應的 Redo Log
  • Undo 的 Page 也像數據一樣緩存在 Buffer Pool 中,跟數據 Page 一起做 LRU 換入換出,以及刷臟。Undo Page 的刷臟也像數據一樣要等到對應的 Redo Log 落盤之後

之所以這樣實現,首要的原因是 MySQL 中的 Undo Log 不只是承擔 Crash Recovery 時保證 Atomic 的作用,更需要承擔 MVCC 對歷史版本的管理的作用,設計目標是高事務併發,方便的管理和維護。因此當做數據更合適。

但既然還叫 Log,就還是需要有 Undo Log 的責任,那就是保證 Crash Recovery 時,如果看到數據的修改,一定要能看到其對應 Undo 的修改,這樣才有機會通過事務的回滾保證 Crash Atomic。標準的 Undo Log 這一步是靠 WAL 實現的,也就是要求 Undo 寫入先於數據落盤。而 InnoDB 中 Undo Log 作為一種特殊的數據,這一步是通過 redo 的 min-transaction 保證的,簡單的說就是數據的修改和對應的 Undo 修改,他們所對應的 Redo Log 被放到同一個 min-transaction 中,同一個 min-transaction 中的所有 Redo Log 在 Crash Recovery 時以一個整體進行重放,要麼全部重放,要麼全部丟棄。

作者:CatKang
鏈接:https://www.zhihu.com/question/267595935/answer/2204949497
來源:知乎

Undo Log 配置的選項

  • innodb_max_undo_log_size:值為,單個 Undo Log 最大可占用的位元組存儲空間;單位為,位元組(預設值是 1 G)。
  • innodb_undo_directory:Undo Log 文件的存儲目錄(預設值是 .\ ,即數據目錄)表示回滾日誌的存儲目錄是數據目錄,數據目錄的位置可以通過查詢變數“datadir”來查看。
  • innodb_undo_log_encrypt:Undo Log 是否加密(預設值是 off,即不加密)。
  • innodb_undo_log_truncate:Undo Log 是否自動截斷回收(預設值是 on,即自動截斷回收)。這個變數有效的前提是設置了使用獨立表空間。
  • innodb_undo_tablespaces:值為 Undo Log 的獨立表空間的數量(預設值是 0,即 Undo Log 沒有獨立的表空間,預設記錄到共用表空間 ibdata 文件中)

file

參考資料

20 | 日誌(下):系統故障,如何恢複數據? (geekbang.org)

MySQL 是怎樣運行的:從根兒上理解 MySQL - 小孩子4919 - 掘金課程 (juejin.cn)

02 | 日誌系統:一條SQL更新語句是如何執行的?-極客時間 (geekbang.org)

關於Innodb undo log的刷新時機? - 知乎 (zhihu.com)

本文來自博客園,作者:真正的飛魚,轉載請註明原文鏈接:https://www.cnblogs.com/feiyu2/p/16672433.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.俄羅斯延長接受簡化版認證流程的日期 2022年8月31日,俄羅斯聯邦政府發佈了第1255號法令,主題為“關於第353號法令附錄18的修正”,主要內容是俄羅斯延長接受“簡化版認證流程”的日期,從2022年9月1日延長至2023年9月1日為止。該法令發佈後立即生效。 “簡化版認證流程”的相關細則可以 ...
  • 1.視圖:view 視圖就是一張虛擬的表。表是真正存數據的,視圖只是顯示查詢結果。 視圖的作用:隱藏表的結構、簡化sql嵌套查詢操作 註意:視圖就是你要查詢數據的一個中間結果集,我們一般只用來做數據查詢的 創建視圖:create view view_name as 查詢語句 例如: mysql> c ...
  • 2022-09-09 1、左連接查詢(left join) 查詢條件的一種,以左表為主根據條件查詢右表數據,如果根據條件查詢右表數據不存在null值填充。 以“students表(id,name,age,gender,is_del,height,c_id,id,name)” "classes表(id ...
  • 不說那種建表的時候 設置好主鍵格式 的 解決方案. 事後諸葛啊. 誰都會不靠譜方案1 改主鍵表結構. 費時! 主鍵已經超長了.說明 數據量相當大. 改表結構的時間成本你能等得起嗎方案2 超長表 改表名作為歷史表 ,新建新表,然後根據業務情況將歷史表數據酌情複製到新表中. (比如最近3個月的數據. 不 ...
  • 摘要:《Index Checkpoints for Instant Recovery in In-Memory Database Systems》是由華為雲資料庫創新Lab一作發表在資料庫領域頂級會議VLDB'2022的學術論文。 本文分享自華為雲社區《VLDB'22 HiEngine極致RTO論文 ...
  • 編者按: Benchmarking 作為一個衡量標尺,可從不同的維度來客觀公正公平的評價相關產品,例如:對應數據測評而言,有 TPC-C、TPC-H,TP-DS 等等。現有的這些測評 TPC-X 標準(Benchmarking)真的適合現有的 OLTP&OLAP 混合型資料庫嗎?現在對於很多 HTA ...
  • 摘要:看GaussDB for Redis強擴展、高可用、強一致、高安全,如何玩轉各大游戲場景 本文分享自華為雲社區《GaussDB為什麼成為游戲行業的心頭愛?》,作者: GaussDB 資料庫 。 在結束忙碌工作回家的地鐵上,難得閑暇的周末下午,和朋友再來一局的入睡前......游戲已經成為了當下 ...
  • MySQL8 Group By 新特性 此生此夜不長好,明月明年何處看。 一、簡介 MySQL8 新特性之 Group By 不再隱式排序。MySQL8對於group by 欄位不再隱式排序,如需要排序,必須顯式加上 order by 子句。 二、MySQL5.7 Group By 數據準備 Sel ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...