MySQL實戰45講 6,7,8

来源:https://www.cnblogs.com/ydssx7/archive/2022/07/23/16513214.html
-Advertisement-
Play Games

06 | 全局鎖和表鎖 :給表加個欄位怎麼有這麼多阻礙? Connection連接與Session會話 通俗來講,會話(Session)是通信雙⽅從開始通信到通信結束期間的⼀個上下文(Context)。這個上下文是⼀段位於伺服器端的記憶體:記錄了本次連接的客戶端機器、通過哪個應用程式、哪個用戶登錄等信 ...


06 | 全局鎖和表鎖 :給表加個欄位怎麼有這麼多阻礙?

Connection連接與Session會話

通俗來講,會話(Session)是通信雙⽅從開始通信到通信結束期間的⼀個上下文(Context)。這個上下文是⼀段位於伺服器端的記憶體:記錄了本次連接的客戶端機器、通過哪個應用程式、哪個用戶登錄等信息。

連接是物理上的客戶端同伺服器的通信鏈路

image

根據加鎖的範圍,MySQL 裡面的鎖大致可以分成全局鎖、表級鎖和行鎖三類。

全局鎖

全局鎖就是對整個資料庫實例加鎖

Flush tables with read lock (FTWRL)

當你需要讓整個庫處於只讀狀態的時候,可以使用這個命令,之後其他線程的以下語句會被阻塞:數據更新語句(數據的增刪改)(DML) 、數據定義語句(包括建表、修改表結構等)(DDL)和更新類事務的提交語句。

全局鎖的典型使用場景是,做全庫邏輯備份。也就是把整庫每個表都 select 出來存成文本。

Q:在可重覆讀隔離級別下開啟一個事務是一致性視圖,這時由於MVCC數據是可以正常更新的,所以為什麼不用這種方式?

A:官方自帶的邏輯備份工具是 mysqldump。當 mysqldump 使用參數–single-transaction 的時候,導數據之前就會啟動一個事務,來確保拿到一致性視圖。但存在一個問題:single-transaction 方法只適用於所有的表使用事務引擎的庫。而MyISAM不支持事務

Q:既然要全庫只讀,為什麼不使用 set global readonly=true 的方式呢?

A:

  • 一是,在有些系統中,readonly 的值會被用來做其他邏輯,比如用來判斷一個庫是主庫還是備庫。因此,修改 global 變數的方式影響面更大,我不建議你使用。
  • 二是,在異常處理機制上有差異。如果執行 FTWRL 命令之後由於客戶端發生異常斷開,那麼 MySQL 會自動釋放這個全局鎖,整個庫回到可以正常更新的狀態。而將整個庫設置為 readonly 之後,如果客戶端發生異常,則資料庫就會一直保持 readonly 狀態,這樣會導致整個庫長時間處於不可寫狀態,風險較高。

表級鎖

表級別的鎖有兩種:一種是表鎖,一種是元數據鎖(meta data lock,MDL)

lock tables … read/write。與 FTWRL 類似,可以用 unlock tables 主動釋放鎖,也可以在客戶端斷開的時候自動釋放。需要註意,lock tables 語法除了會限制別的線程的讀寫外,也限定了本線程接下來的操作對象。

另一類表級的鎖是 MDL(metadata lock)。

MDL作用是防止DDLDML併發的衝突,

MDL 不需要顯式使用,在訪問一個表的時候會被自動加上。事務中的 MDL 鎖,在語句執行開始時申請,但是語句結束後並不會馬上釋放,而會等到整個事務提交後再釋放。

image

我們可以看到 session A 先啟動,這時候會對錶 t 加一個 MDL 讀鎖。由於 session B 需要的也是 MDL 讀鎖,因此可以正常執行。之後 session C 會被 blocked,是因為 session A 的 MDL 讀鎖還沒有釋放,而 session C 需要 MDL 寫鎖,因此只能被阻塞。並且之後所有要在表 t 上新申請 MDL 讀鎖的請求也會被 session C 阻塞

MDL 會直到事務提交才釋放,在做表結構變更的時候,一定要小心不要導致鎖住線上查詢和更新

Q:如何安全地給小表加欄位?

A:首先我們要解決長事務,事務不提交,就會一直占著 MDL 鎖。如果你要做 DDL 變更的表剛好有長事務在執行,要考慮先暫停 DDL,或者 kill 掉這個長事務

Q:如果你要變更的表是一個熱點表,雖然數據量不大,但是上面的請求很頻繁,而你不得不加個欄位,你該怎麼做呢?

A:這時候 kill 可能未必管用,因為新的請求馬上就來了。比較理想的機制是,在 alter table 語句裡面設定等待時間如果在這個指定的等待時間裡面能夠拿到 MDL 寫鎖最好,拿不到也不要阻塞後面的業務語句,先放棄。之後開發人員或者 DBA 再通過重試命令重覆這個過程

Q:備份一般都會在備庫上執行,你在用–single-transaction 方法做邏輯備份的過程中,如果主庫上的一個小表做了一個 DDL,比如給一個表上加了一列。這時候,從備庫上會看到什麼現象呢?

A:假設這個 DDL 是針對錶 t1 的, 備份過程中幾個關鍵的語句:

/* 在備份開始的時候,為了確保 RR(可重覆讀)隔離級別,再設置一次 RR 隔離級別 (Q1)*/
Q1:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
/* 啟動事務,這裡用 WITH CONSISTENT SNAPSHOT 確保這個語句執行完就可以得到一個一致性視圖(Q2) */
Q2:START TRANSACTION  WITH CONSISTENT SNAPSHOT;

/* 設置一個保存點,這個很重要(Q3); */
Q3:SAVEPOINT sp;
/* show create 是為了拿到表結構 (Q4)    時刻 1 */
Q4:show create table `t1`;
/* 正式導數據 (Q5)   時刻 2 */
Q5:SELECT * FROM `t1`;
/* 回滾到 SAVEPOINT sp,在這裡的作用是釋放 t1 的 MDL 鎖  時刻 3 */
Q6:ROLLBACK TO SAVEPOINT sp;
/* 時刻 4 */
/* other tables */

DDL 從主庫傳過來的時間按照效果不同,分為四個時刻。

題目設定為小表,我們假定到達後,如果開始執行,則很快能夠執行完成。

  1. 如果在 Q4 語句執行之前到達,現象:沒有影響,備份拿到的是 DDL 後的表結構。
  2. 如果在“時刻 2”到達,則表結構被改過,Q5 執行的時候,報 Table definition has changed, please retry transaction,現象:mysqldump 終止;
  3. 如果在“時刻 2”和“時刻 3”之間到達,mysqldump 占著 t1 的 MDL 讀鎖,binlog 被阻塞,現象:主從延遲,直到 Q6 執行完成。
  4. 從“時刻 4”開始,mysqldump 釋放了 MDL 讀鎖,現象:沒有影響,備份拿到的是 DDL 前的表結構。

07 | 行鎖功過:怎麼減少行鎖對性能的影響?

MySQL 的行鎖

MySQL 的行鎖是在引擎層由各個引擎自己實現的。但並不是所有的引擎都支持行鎖,比如 MyISAM 引擎就不支持行鎖。

行鎖就是針對數據表中行記錄的鎖。這很好理解,比如事務 A 更新了一行,而這時候事務 B 也要更新同一行,則必須等事務 A 的操作完成後才能進行更新。

兩階段鎖

image

事務 A 持有的兩個記錄的行鎖,都是在 commit 的時候才釋放的。事務 B 的 update 語句會被阻塞,直到事務 A 執行 commit 之後,事務 B 才能繼續執行。

在 InnoDB 事務中,行鎖是在需要的時候才加上的,但並不是不需要了就立刻釋放,而是要等到事務結束時才釋放。這個就是兩階段鎖協議。

如果你的事務中需要鎖多個行,要把最可能造成鎖衝突、最可能影響併發度的鎖儘量往後放

死鎖和死鎖檢測

當併發系統中不同線程出現迴圈資源依賴,涉及的線程都在等待別的線程釋放資源時,就會導致這幾個線程都進入無限等待的狀態,稱為死鎖。

image

這時候,事務 A 在等待事務 B 釋放 id=2 的行鎖,而事務 B 在等待事務 A 釋放 id=1 的行鎖。 事務 A 和事務 B 在互相等待對方的資源釋放,就是進入了死鎖狀態。

當出現死鎖以後,有兩種策略

  • 一種策略是,直接進入等待,直到超時。這個超時時間可以通過參數 innodb_lock_wait_timeout 來設置。
  • 另一種策略是,發起死鎖檢測,發現死鎖後,主動回滾死鎖鏈條中的某一個事務,讓其他事務得以繼續執行。將參數 innodb_deadlock_detect 設置為 on,表示開啟這個邏輯。每當一個事務被鎖的時候,就要看看它所依賴的線程有沒有被別人鎖住 n2複雜度),如此迴圈,最後判斷是否出現了迴圈等待,也就是死鎖。(死鎖的四個必要條件 互斥,請求與保持,不可剝奪,迴圈等待)

死鎖檢測要耗費大量的 CPU 資源

Q:怎麼解決由這種熱點行更新導致的性能問題呢?

A:

  • 臨時把死鎖檢測關掉。可能會出現大量的超時,這是業務有損的。
  • 控制併發度,在中間件實現,對於相同行的更新,在進入引擎之前排隊。這樣在 InnoDB 內部就不會有大量的死鎖檢測工作了。
  • 從設計上優化,拆分一行改為邏輯上的多行,隨機選一個加上,再求和

Q:如果你要刪除一個表裡面的前 10000 行數據,有以下三種方法可以做到:

  • 第一種,直接執行 delete from T limit 10000;
  • 第二種,在一個連接中迴圈執行 20 次 delete from T limit 500;
  • 第三種,在 20 個連接中同時執行 delete from T limit 500。

選擇哪一種方法呢?為什麼呢?

A:

第二種方式是相對較好的。

第一種方式(即:直接執行 delete from T limit 10000)裡面,單個語句占用時間長,鎖的時間也比較長;而且大事務還會導致主從延遲。

第三種方式(即:在 20 個連接中同時執行 delete from T limit 500),會人為造成鎖衝突。

08 | 事務到底是隔離的還是不隔離的?

如果是可重覆讀隔離級別,事務 T 啟動的時候會創建一個視圖 read-view,之後事務 T 執行期間,即使有其他事務修改了數據,事務 T 看到的仍然跟在啟動時看到的一樣。也就是說,一個在可重覆讀隔離級別下執行的事務,好像與世無爭,不受外界影響。

一個事務要更新一行,如果剛好有另外一個事務擁有這一行的行鎖,它又不能這麼超然了,會被鎖住,進入等待狀態

Q:既然進入了等待狀態,那麼等到這個事務自己獲取到行鎖要更新數據的時候,它讀到的值是什麼呢

舉一個例子,下麵是一個只有兩行的表的初始化語句。

mysql> CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `k` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);

事務開始時間點,分為兩種情況:

1)start transaction 時,是第一條語句的執行時間點,就是事務開始的時間點,第一條select語句建立一致性讀的snapshot;

2)start transaction with consistent snapshot 時,則是立即建立本事務的一致性讀snapshot,當然也開始事務了;

image

在這個例子中,事務 C 沒有顯式地使用 begin/commit,表示這個 update 語句本身就是一個事務,語句完成的時候會自動提交。

事務 B 在更新了行之後查詢 ;

事務 A 在一個只讀事務中查詢,並且時間順序上是在事務 B 的查詢之後。

結果:事務 B 查到的 k 的值是 3,而事務 A 查到的 k 的值是 1

A:

不妨做如下假設:

  1. 事務 A 開始前,系統裡面只有一個活躍事務 ID 是 99;
  2. 事務 A、B、C 的版本號分別是 100、101、102,且當前系統里只有這四個事務;
  3. 三個事務開始前,(1,1)這一行數據的 row trx_id 是 90

image

從圖中可以看到,第一個有效更新是事務 C,把數據從 (1,1) 改成了 (1,2)。這時候,這個數據的最新版本的 row trx_id 是 102,而 90 這個版本已經成為了歷史版本。

第二個有效更新是事務 B,把數據從 (1,2) 改成了 (1,3)。這時候,這個數據的最新版本(即 row trx_id)是 101,而 102 又成為了歷史版本。

在事務 A 查詢的時候,其實事務 B 還沒有提交,但是它生成的 (1,3) 這個版本已經變成當前版本了。但這個版本對事務 A 必須是不可見的,否則就變成臟讀了。

事務 A 要來讀數據了,它的視圖數組是 [99,100]。當然了,讀數據都是從當前版本讀起的。所以,事務 A 查詢語句的讀數據流程是這樣的:

  • 找到 (1,3) 的時候,判斷出 row trx_id=101,比高水位大,處於紅色區域,不可見;
  • 接著,找到上一個歷史版本,一看 row trx_id=102,比高水位大,處於紅色區域,不可見;
  • 再往前找,終於找到了(1,1),它的 row trx_id=90,比低水位小,處於綠色區域,可見。

總結:

一個數據版本,對於一個事務視圖來說,除了自己的更新總是可見以外,有三種情況:

  1. 版本未提交,不可見;
  2. 版本已提交,但是是在視圖創建後提交的,不可見;
  3. 版本已提交,而且是在視圖創建前提交的,可見。

兩個“視圖”的概念

在 MySQL 里,有兩個“視圖”的概念:

  • 一個是 view。它是一個用查詢語句定義的虛擬表,在調用的時候執行查詢語句並生成結果。創建視圖的語法是 create view … ,而它的查詢方法與表一樣。
  • 另一個是 InnoDB 在實現 MVCC 時用到的一致性讀視圖,即 consistent read view,用於支持 RC(Read Committed,讀提交)和 RR(Repeatable Read,可重覆讀)隔離級別的實現。

它沒有物理結構,作用是事務執行期間用來定義“我能看到什麼數據”。

“快照”在 MVCC 里是怎麼工作的?

在可重覆讀隔離級別下,事務在啟動的時候就“拍了個快照”。註意,這個快照是基於整庫的

InnoDB 裡面每個事務有一個唯一的事務 ID,叫作 transaction id。它是在事務開始的時候向 InnoDB 的事務系統申請的,是按申請順序嚴格遞增的

每行數據也都是有多個版本的。每次事務更新數據的時候,都會生成一個新的數據版本,並且把 transaction id 賦值給這個數據版本的事務 ID,記為 row trx_id。同時,舊的數據版本要保留,並且在新的數據版本中,能夠有信息可以直接拿到它

也就是說,數據表中的一行記錄,其實可能有多個版本 (row),每個版本有自己的 row trx_id。

image

圖中虛線框里是同一行數據的 4 個版本,當前最新版本是 V4,k 的值是 22,它是被 transaction id 為 25 的事務更新的,因此它的 row trx_id 也是 25。

實際上,圖 2 中的三個虛線箭頭,就是 undo log;而 V1、V2、V3 並不是物理上真實存在的而是每次需要的時候根據當前版本和 undo log 計算出來的。比如,需要 V2 的時候,就是通過 V4 依次執行 U3、U2 算出來

按照可重覆讀的定義,一個事務啟動的時候,能夠看到所有已經提交的事務結果。但是之後,這個事務執行期間,其他事務的更新對它不可見。因此,一個事務只需要在啟動的時候聲明說,“以我啟動的時刻為準,如果一個數據版本是在我啟動之前生成的,就認;如果是我啟動以後才生成的,我就不認,我必須要找到它的上一個版本”。當然,如果“上一個版本”也不可見,那就得繼續往前找。還有,如果是這個事務自己更新的數據,它自己還是要認的

在實現上, InnoDB 為每個事務構造了一個數組,用來保存這個事務啟動瞬間當前正在“活躍”的所有事務 ID。“活躍”指的就是,啟動了但還沒提交

數組裡面事務 ID 的最小值記為低水位,當前系統裡面已經創建過的事務 ID 的最大值加 1 記為高水位。

這個視圖數組和高水位,就組成了當前事務的一致性視圖(read-view)

數據版本的可見性規則,就是基於數據的 row trx_id 和這個一致性視圖的對比結果得到的。

這個視圖數組把所有的 row trx_id 分成了幾種不同的情況。

  1. 如果落在綠色部分,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數據是可見的;
  2. 如果落在紅色部分,表示這個版本是由將來啟動的事務生成的,是肯定不可見的;
  3. 如果落在黃色部分,那就包括兩種情況
    a. 若 row trx_id 在數組中,表示這個版本是由還沒提交的事務生成的,不可見;
    b. 若 row trx_id 不在數組中,表示這個版本是已經提交了的事務生成的,可見。

image

有了這個聲明後,系統裡面隨後發生的更新,就跟這個事務看到的內容無關了。因為之後的更新,生成的版本一定屬於上面的 2 或者 3(a) 的情況,而對它來說,這些新的數據版本是不存在的,所以這個事務的快照,就是“靜態”的了。

如果有一個事務,它的低水位是 18,那麼當它訪問這一行數據時,就會從 V4 通過 U3 計算出 V3,所以在它看來,這一行的值是 11。

InnoDB 利用了“所有數據都有多個版本”的這個特性,實現了“秒級創建快照”的能力。

更新邏輯

Q:事務 B 的 update 語句,如果按照一致性讀,好像結果不對哦?

事務 B 的視圖數組是先生成的,之後事務 C 才提交,不是應該看不見 (1,2) 嗎,怎麼能算出 (1,3) 來?

image

A:如果事務 B 在更新之前查詢一次數據,這個查詢返回的 k 的值確實是 1。

但是,當它要去更新數據的時候,就不能再在歷史版本上更新了,否則事務 C 的更新就丟失了。因此,事務 B 此時的 set k=k+1 是在(1,2)的基礎上進行的操作

更新數據都是先讀後寫的,而這個讀,只能讀當前的值,稱為“當前讀”(current read)。

因此,在更新的時候,當前讀拿到的數據是 (1,2),更新後生成了新版本的數據 (1,3),這個新版本的 row trx_id 是 101。所以,在執行事務 B 查詢語句的時候,一看自己的版本號是 101,最新數據的版本號也是 101,是自己的更新,可以直接使用,所以查詢得到的 k 的值是 3

除了 update 語句外,select 語句如果加鎖,也是當前讀。

所以,如果把事務 A 的查詢語句 select * from t where id=1 修改一下,加上 lock in share mode 或 for update,也都可以讀到版本號是 101 的數據,返回的 k 的值是 3

下麵這兩個 select 語句,就是分別加了讀鎖(S 鎖,共用鎖)和寫鎖(X 鎖,排他鎖)。

select k from t where id=1 lock in share mode;
select k from t where id=1 for update;

Q:假設事務 C 不是馬上提交的,而是變成了下麵的事務 C’,會怎麼樣呢?

image

事務 C’的不同是,更新後並沒有馬上提交,在它提交前,事務 B 的更新語句先發起了。前面說過了,雖然事務 C’還沒提交,但是 (1,2) 這個版本也已經生成了,並且是當前的最新版本。那麼,事務 B 的更新語句會怎麼處理呢

A:考慮兩階段鎖協議,事務 C’沒提交,也就是說 (1,2) 這個版本上的寫鎖還沒釋放。而事務 B 是當前讀,必須要讀最新版本,而且必須加鎖,因此就被鎖住了必須等到事務 C’釋放這個鎖,才能繼續它的當前讀

事務的可重覆讀的能力是怎麼實現的?

可重覆讀的核心就是一致性讀(consistent read);而事務更新數據的時候,只能用當前讀。如果當前的記錄的行鎖被其他事務占用的話,就需要進入鎖等待

讀提交的邏輯和可重覆讀

而讀提交的邏輯和可重覆讀的邏輯類似,它們最主要的區別是:

  • 在可重覆讀隔離級別下,只需要在事務開始的時候創建一致性視圖,之後事務里的其他查詢都共用這個一致性視圖;
  • 在讀提交隔離級別下,每一個語句執行前都會重新算出一個新的視圖。“start transaction with consistent snapshot; ”的意思是從這個語句開始,創建一個持續整個事務的一致性快照。所以,在讀提交隔離級別下,這個用法就沒意義了,等效於普通的 start transaction。

導致:

  • 對於可重覆讀,查詢只承認在事務啟動前就已經提交完成的數據;
  • 對於讀提交,查詢只承認在語句啟動前就已經提交完成的數據;

Q:在讀提交隔離級別下,事務 A 和事務 B 的查詢語句查到的 k,分別應該是多少呢?

A:

下麵是讀提交時的狀態圖,可以看到這兩個查詢語句的創建視圖數組的時機發生了變化,就是圖中的 read view 框。(註意:這裡,我們用的還是事務 C 的邏輯直接提交,而不是事務 C’)

image

這時,事務 A 的查詢語句的視圖數組是在執行這個語句的時候創建的,時序上 (1,2)、(1,3) 的生成時間都在創建這個視圖數組的時刻之前。但是,在這個時刻:

  • (1,3) 還沒提交,屬於情況 1,不可見;
  • (1,2) 提交了,屬於情況 3,可見。

所以,這時候事務 A 查詢語句返回的是 k=2,事務 B 查詢結果 k=3,能看到已提交的。。

Q:用下麵的表結構和初始化語句作為試驗環境,事務隔離級別是可重覆讀。現在,我要把所有“欄位 c 和 id 值相等的行”的 c 值清零,但是卻發現了一個“詭異”的、改不掉的情況。請你構造出這種情況,並說明其原理。

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, c) values(1,1),(2,2),(3,3),(4,4);

image

A:如何構造一個“數據無法修改”的場景。

image

image


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

-Advertisement-
Play Games
更多相關文章
  • 1.保障應用程式埠的連通性 通常情況下伺服器的防火牆通常都是開啟的狀態,所以我們需要保證我們部署應用程式的埠是開啟了相應的訪問許可權,否則我們的應用程式將無法被外界進行訪問。這裡為了快速測試應用程式的埠連通性,我們使用比較方便的Telnet工具進行測試,該工具的安裝包內置在Windows操作系統 ...
  • 一:背景 1. 講故事 前段時間有位朋友說他的程式 CPU 出現了暴漲現象,由於程式是買來的,所以問題就比較棘手了,那既然找到我,就想辦法幫朋友找出來吧,分析下來,問題比較經典,有必要和大家做一下分享。 二:WinDbg 分析 1. CPU 真的爆高嗎 一直關註這個系列的朋友應該知道,用 !tp 驗 ...
  • “don't worry”,部署ASP.NET Core應用可以和原來部署.NET Framework的ASP.NET應用一樣的簡單,還是“熟悉的配方,熟悉的味道”,甚至提供了更加便捷的Kestrel部署方式,下麵主要介紹在windows平臺下兩種常用部署方式: 方式一:Kestrel部署Web應用 ...
  • 前言 .NET在跨平臺後對於應用的部署而言,不在像.NET Framework的時候那麼單一化了,一個.NET Core應用的部署工作就可以涉及到很多知識點。 就對於windows而言,我們可以選擇使用IIS和Kestrel作為我們的Web伺服器。既可以把網站的部署用“進程內托管”方式插入IIS管道 ...
  • Linux 的應用安裝,升級和卸載 1.源碼安裝:太古老了,基本沒人用了 2.通過紅帽的包管理器安裝: 語法:rpm [參數] 軟體包名 (1)參數: i :安裝; U:升級; e:清除(卸載)軟體包; v:驗證包; h:顯示進度條; q:查詢選項; a:查詢/驗證所有包; (2)常用參數組合: - ...
  • 現象 在ubuntu上編譯內核時,apt-get source時出現如下warning: W: Download is performed unsandboxed as root as file '/var/cache/apt/archives/partial/samba-libs_2%3a4.5. ...
  • 10 | MySQL為什麼有時候會選錯索引? 使用哪個索引是由 MySQL 來確定的 可能遇到的情況:一條本來可以執行得很快的語句,卻由於 MySQL 選錯了索引,而導致執行速度變得很慢 先建一個簡單的表,表裡有 a、b 兩個欄位,並分別建上索引: CREATE TABLE `t` ( `id` i ...
  • 11 | 怎麼給字元串欄位加索引? Q:如何在郵箱這樣的欄位上建立合理的索引? 用戶表的定義: create table SUser( ID bigint unsigned primary key, email varchar(64), ... )engine=innodb; 由於要使用郵箱登錄,所 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...