新聞中心
在現(xiàn)代計算機(jī)系統(tǒng)中,數(shù)據(jù)庫是維護(hù)數(shù)據(jù)的主要工具。由于實(shí)際工作中可能有多個用戶需要同時訪問數(shù)據(jù)庫,因此實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫是非常必要的。在本文中,我們將介紹如何使用 C 編程語言實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的方法。

1. 數(shù)據(jù)庫和并發(fā)
在了解如何實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫之前,我們首先需要了解數(shù)據(jù)庫和并發(fā)之間的關(guān)系。具體來說,一個數(shù)據(jù)庫是一個存儲和管理數(shù)據(jù)的系統(tǒng),它需要支持多個用戶同時訪問和操作數(shù)據(jù)。在這種情況下,我們稱這些操作為并發(fā)操作。在并發(fā)操作中,我們需要確保多個用戶操作之間的數(shù)據(jù)一致性和完整性,以避免出現(xiàn)數(shù)據(jù)沖突和錯誤。
2. 并發(fā)訪問數(shù)據(jù)庫的方法
為了實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫,我們需要考慮以下幾個方面:
2.1. 數(shù)據(jù)庫連接
在使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫之前,我們需要確保已經(jīng)建立了數(shù)據(jù)庫連接。一旦有多個用戶同時訪問數(shù)據(jù)庫,這些用戶將共享同一個數(shù)據(jù)庫連接。因此,我們需要確保每個用戶獲得的都是一個獨(dú)立的數(shù)據(jù)庫連接,并且這些連接之間不會相互干擾。
2.2. 數(shù)據(jù)庫操作
在多個用戶同時訪問數(shù)據(jù)庫時,每個用戶將執(zhí)行自己的數(shù)據(jù)庫操作。在這種情況下,我們需要確保每個用戶執(zhí)行的數(shù)據(jù)庫操作是正確的,并且不會影響其他用戶的操作。為此,我們可以使用鎖定機(jī)制(mutex)或事務(wù)(transaction)來確保數(shù)據(jù)庫的正確性和完整性。
2.3. 線程
當(dāng)我們使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫時,我們通常會使用線程來實(shí)現(xiàn)并發(fā)操作。在這種情況下,我們需要確保每個線程都能夠獨(dú)立運(yùn)行,并且它們之間不會相互干擾。為了避免競爭條件和錯誤,我們可以使用線程同步機(jī)制,如互斥鎖(mutex)和條件變量(condition variable),來確保線程之間的正確的序列和順序執(zhí)行。
3. 使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的示例
下面是一個使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的簡單示例。
3.1. 數(shù)據(jù)庫連接
我們可以使用以下代碼片段來建立一個數(shù)據(jù)庫連接:
“`c
#include
#include
#include
// 定義數(shù)據(jù)庫連接
sqlite3 *db;
// 建立數(shù)據(jù)庫連接
int open_database(const char *filename) {
int rc = sqlite3_open(filename, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, “無法打開數(shù)據(jù)庫: %s\n”, sqlite3_errmsg(db));
sqlite3_close(db);
return rc;
}
return SQLITE_OK;
}
“`
3.2. 數(shù)據(jù)庫操作
在多個用戶同時訪問數(shù)據(jù)庫時,我們需要確保每個用戶執(zhí)行的數(shù)據(jù)庫操作是正確的,并且不會影響其他用戶的操作。下面是一個使用事務(wù)來實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的示例:
“`c
// 開始事務(wù)
sqlite3_exec(db, “BEGIN;”, NULL, NULL, NULL);
// 執(zhí)行數(shù)據(jù)庫操作
int rc = sqlite3_exec(db, “UPDATE table SET column1 = value1 WHERE id = 1;”, NULL, NULL, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “執(zhí)行數(shù)據(jù)庫操作出錯: %s\n”, sqlite3_errmsg(db));
sqlite3_exec(db, “ROLLBACK;”, NULL, NULL, NULL);
return rc;
}
// 提交事務(wù)
sqlite3_exec(db, “COMMIT;”, NULL, NULL, NULL);
“`
3.3. 線程
當(dāng)我們使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫時,我們通常會使用線程來實(shí)現(xiàn)并發(fā)操作。下面是一個使用線程實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的示例:
“`c
#include
#include
#include
#include
// 定義數(shù)據(jù)庫連接
sqlite3 *db;
// 建立數(shù)據(jù)庫連接
int open_database(const char *filename) {
int rc = sqlite3_open(filename, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, “無法打開數(shù)據(jù)庫: %s\n”, sqlite3_errmsg(db));
sqlite3_close(db);
return rc;
}
return SQLITE_OK;
}
// 線程函數(shù)
void *thread_function(void *arg) {
// 開始事務(wù)
sqlite3_exec(db, “BEGIN;”, NULL, NULL, NULL);
// 執(zhí)行數(shù)據(jù)庫操作
int rc = sqlite3_exec(db, “UPDATE table SET column1 = value1 WHERE id = 1;”, NULL, NULL, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “執(zhí)行數(shù)據(jù)庫操作出錯: %s\n”, sqlite3_errmsg(db));
sqlite3_exec(db, “ROLLBACK;”, NULL, NULL, NULL);
return (void *)rc;
}
// 提交事務(wù)
sqlite3_exec(db, “COMMIT;”, NULL, NULL, NULL);
return (void *)rc;
}
int mn() {
// 建立數(shù)據(jù)庫連接
open_database(“test.db”);
// 創(chuàng)建線程
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_function, NULL);
// 等待線程完成
pthread_join(thread_id, NULL);
// 關(guān)閉數(shù)據(jù)庫連接
sqlite3_close(db);
return 0;
}
“`
4.
相關(guān)問題拓展閱讀:
- 大型網(wǎng)站數(shù)據(jù)庫系統(tǒng),怎么連接那么多并發(fā)數(shù)量的?
- 怎樣在C語言中編寫多個程序并發(fā)執(zhí)行的程序
大型網(wǎng)站數(shù)據(jù)庫系統(tǒng),怎么連接那么多并發(fā)數(shù)量的?
現(xiàn)象
Syench對MySQL進(jìn)行壓測, 并發(fā)數(shù)過大(>5k)時, Syench建立連接的步驟會超時.
猜想
猜想: 直覺上這很簡單, Syench每建立一個連接, 都要消耗一個線程, 資源消耗過大導(dǎo)致超時.
驗(yàn)證: 修改Syench源碼, 調(diào)大超時時間, 仍然會發(fā)生超時.
檢查環(huán)境
猜想失敗, 回到常規(guī)的環(huán)境檢查:
MySQL error log 未見異常.
syslog 未見異常.
tcpdump 觀察網(wǎng)絡(luò)包未見異常, 連接能完成正常的三次握手; 只觀察到在出問題的連接中, 有一部分的TCP握手的之一個SYN包發(fā)生了重傳, 另一梁轎迅部分沒有發(fā)生重傳.
自己寫一個簡單的并發(fā)發(fā)生器, 替換syench, 可重現(xiàn)場景. 排除syench的影響
猜想2
懷疑 MySQL 在應(yīng)用層因?yàn)槟撤N原因, 沒有發(fā)送握手包, 比如卡在某一個流程上:
檢查MySQL堆棧未見異常, 仿佛MySQL在應(yīng)用層沒有看到新連接進(jìn)入.
通過strace檢查MySQL, 發(fā)現(xiàn) accept() 調(diào)用確實(shí)沒有感知到新連接.
懷疑是OS的原因, Google之, 得到參考文檔: A TCP “stuck” connection mystery【
分析
參考文檔中的現(xiàn)象跟目前的狀況很類似, 簡述如下:
正常的TCP連接流程:
Client 向 Server 發(fā)起連接請求, 發(fā)送SYN.
Server 預(yù)留連接資源, 向 Client 回復(fù)SYN-ACK.
Client 向 Server 回復(fù)ACK.
Server 收到 ACK, 連接建立.
在業(yè)務(wù)層上, Client和Server間進(jìn)行通訊.
當(dāng)發(fā)生類似SYN-flood的現(xiàn)象時, TCP連接的流程會使用SYN-cookie, 變?yōu)?
Client 向 Server 發(fā)起連接請求, 發(fā)送SYN.
Server 不預(yù)留連接資源, 向 Client 回復(fù)SYN-ACK, 包中附帶有帆陪簽名A.
Client 向 Server 回復(fù)ACK, 附帶 f(簽名A) (對簽名進(jìn)行運(yùn)算的結(jié)果).
Server 驗(yàn)證簽名, 分配連接資源, 連接建立.
在業(yè)務(wù)層上, Client和Server間進(jìn)行通訊.
當(dāng)啟用SYN-cookie時, 第3步的ACK包因?yàn)?nbsp;某種原因 丟失, 那么:
從Client的視角, 連接已經(jīng)建立.
從Server的視角, 連接并不存在, 既沒有建立, 也沒有”即將建立” (若不啟用SYN-cookie, Server會知道某個連接”即將建立”)
發(fā)生這種情況時:
若業(yè)務(wù)層的之一個包應(yīng)是從 Client 發(fā)往 Server, 則會進(jìn)行重發(fā)或拋出連接錯誤
若業(yè)務(wù)層的之一個包應(yīng)是從 Server 發(fā)往 Client的, Server不會發(fā)出之一個包. MySQL的故障就屬于這種情況.
TCP握手的第三步ACK包為什么丟失
參考文檔中, 對于TCP握手的第三橡此步ACK包的丟失原因, 描述為:
Some of these packets get lost because some buffer somewhere overflows.
我們可以通過Systemtap進(jìn)一步探究原因. 通過一個簡單的腳本:
probe kernel.function(“cookie_v4_check”).return
{
source_port = @cast($skb->head + $skb->transport_header, “struct tcphdr”)->source
printf(“source=%d, return=%d\n”,readable_port(source_port), $return)
}
function readable_port(port) {
return (port & ((1> 8)
}
觀察結(jié)果, 可以確認(rèn)cookie_v4_check (syn cookie機(jī)制進(jìn)行包簽名檢查的函數(shù))會返回 NULL(0). 即驗(yàn)證是由于syn cookie驗(yàn)證不通過, 導(dǎo)致TCP握手的第三步ACK包不被接受.
之后就是對其中不同條件進(jìn)行觀察, 看看是哪個條件不通過. 最終原因是accept隊列滿(sk_acceptq_is_full):
static inline bool sk_acceptq_is_full(const struct sock *sk){ return sk->sk_ack_backlog > sk- >sk_max_ack_backlog;}
恢復(fù)故障與日志的正關(guān)聯(lián)
在故障處理的一開始, 我們就檢查了syslog, 結(jié)論是未見異常.
當(dāng)整個故障分析完成, 得知了故障與syn cookie有關(guān), 回頭看syslog, 里面是有相關(guān)的信息, 只是和故障發(fā)生的時間不匹配, 沒有正關(guān)聯(lián), 因此被忽略.
檢查Linux源碼:
if (!queue->synflood_warned &&
sysctl_tcp_syncookies != 2 &&
xchg(&queue->synflood_warned, 1) == 0)
pr_info(“%s: Possible SYN flooding on port %d. %s.
Check SNMP counters.\n”,
proto, ntohs(tcp_hdr(skb)->dest), msg);
可以看到日志受到了抑制, 因此日志與故障的正關(guān)聯(lián)被破壞.
粗看源碼, 每個listen socket只會發(fā)送一次告警日志, 要獲得日志與故障的正關(guān)聯(lián), 必須每次測試重啟MySQL.
解決方案
這種故障一旦形成, 難以檢測; 系統(tǒng)日志中只會出現(xiàn)一次, 在下次重啟MySQL之前就不會再出現(xiàn)了; Client如果沒有合適的超時機(jī)制, 萬劫不復(fù).
解決方案:
1. 修改MySQL的協(xié)議, 讓Client先發(fā)握手包. 顯然不現(xiàn)實(shí).
2. 關(guān)閉syn_cookie. 有安全的人又要跳出來了.
3. 或者調(diào)高syn_cookie的觸發(fā)條件 (syn backlog長度). 降低系統(tǒng)對syn flood的敏感度, 使之可以容忍業(yè)務(wù)的syn波動.
有多個系統(tǒng)參數(shù)混合影響syn backlog長度, 參看【
下圖為精華總結(jié)
請點(diǎn)擊輸入圖片描述
按我個人經(jīng)驗(yàn)有以下幾種方法:1.在連接數(shù)據(jù)庫的時候可以優(yōu)化,使用連接池。主要就是不要頻繁地創(chuàng)建,銷毀連接。這是很費(fèi)時的一個操作。因此,使用連接池來代替普通的建立連接操作,能提高并發(fā)度。2. 使用緩存技術(shù)。并不是每次都需要去數(shù)據(jù)庫里面查詢的,我們其實(shí)可以把前一次的查詢結(jié)果放在內(nèi)存里,如果下凱巧一次盯凱鍵用戶來查詢相同的內(nèi)容,直接內(nèi)存返回即可,不需要再次查詢。這樣可以大大降低查詢頻率。3.使用分布式技術(shù),將數(shù)據(jù)庫分布在多臺服務(wù)孫穗器上,同時也將用戶分區(qū)(如根據(jù)用戶ID的哈希值分區(qū)),不同的服務(wù)器負(fù)責(zé)不同用戶群,這樣就能大大減少單臺服務(wù)器的負(fù)載,使得整體的吞吐量提高。這幾樣技術(shù)可以同時使用,你的并發(fā)數(shù)量將獲得非常大的提高。
在連接數(shù)據(jù)庫的時候可以優(yōu)化,使用連接池。主要就是不要頻繁地創(chuàng)建,銷毀連接。這是很費(fèi)時的一個操作。因此,使用連接池來代替普通的建立連接操作,能提高并發(fā)度。
使用緩存技術(shù),并不是每次都需要去數(shù)據(jù)庫里面查詢的,我們其實(shí)可以把前一次的查詢結(jié)果放在內(nèi)存里,如果下一次用戶來查詢相同的內(nèi)容,直接內(nèi)存返回即可,不需要再次查詢。這樣可以大大降低查詢頻率。
使用分布式技術(shù),將數(shù)據(jù)庫分布在多臺服務(wù)器上,同時也將用戶分區(qū)(如根據(jù)用戶ID的哈希值分區(qū)),不同的服務(wù)器負(fù)責(zé)不同用戶群,這樣就能大大減少單臺服務(wù)器的負(fù)載,使得整體的吞吐量提高。這幾樣技術(shù)可以同時使用,你的并發(fā)數(shù)量將獲得非常大的提高。
大型數(shù)據(jù)庫介紹:
1 SQL Server
概括地說,SQL Server具有如下特點(diǎn):
A客戶/服務(wù)器體系結(jié)構(gòu);
B圖形化的用戶界面,使系統(tǒng)的管理更加直觀和簡單。
C豐富的編程接口,為用戶進(jìn)行應(yīng)用程序設(shè)計提拱了更大的選擇余地。
D與Windows NT操作系統(tǒng)的有機(jī)集成,多線程體系結(jié)構(gòu)設(shè)計,提供了系統(tǒng)對用戶并發(fā)訪問的速度。
E對Web技術(shù)的支持,使用戶能夠很容易地將數(shù)據(jù)庫中的數(shù)據(jù)發(fā)布到網(wǎng)上。
F價格上的優(yōu)勢。與其他一些大型數(shù)據(jù)庫系統(tǒng)。如Oracle、Sybase等相比,SQL Server的價格非常便宜。
G作為微軟在Windows系列平臺上開發(fā)的數(shù)據(jù)庫,SQL Server一經(jīng)推出就以其易用性和兼容性得到了很多用戶的青睞,是Windows環(huán)境商業(yè)應(yīng)用的首選數(shù)據(jù)庫。
2 Oracle
甲骨文公司(Oracle)的產(chǎn)品,可以運(yùn)行于很多操作系統(tǒng)之上(包括Windows),是大型企業(yè)級數(shù)據(jù)庫。Oracle它是以高級結(jié)構(gòu)化查詢語言為基礎(chǔ)的大型關(guān)系型數(shù)據(jù)庫,是目前更流行的客戶/服務(wù)器體系機(jī)構(gòu)的數(shù)據(jù)庫之一。提供對Internet全面支持的管畝櫻閉理平臺和系統(tǒng)集成工具,完全支持所有的工業(yè)標(biāo)準(zhǔn),占有相當(dāng)大的市場份額。因其專業(yè)性較強(qiáng),操作繁雜,不易上手,價格較高,一般作為UNIX下的應(yīng)用較多,適于大型網(wǎng)站選用。
3 DB2
IBM公司的產(chǎn)品,可以運(yùn)行于很多操作系統(tǒng)上(包括Windows),是大型企業(yè)級數(shù)據(jù)庫。DB2具有很好的并行性。把數(shù)據(jù)庫管理擴(kuò)充到了并行的、多節(jié)點(diǎn)的環(huán)境。其操作簡單、兼容性好,廣泛應(yīng)用于大型企業(yè)。
DB2是內(nèi)嵌于IBM的AS/400系統(tǒng)上的數(shù)據(jù)庫管理系統(tǒng),直接由硬件支持。它支持標(biāo)準(zhǔn)的SQL語言,具有與異種數(shù)據(jù)庫相連的GATEWAY。因此他具有速度快、可考性好的優(yōu)點(diǎn)。但是,只有硬件平臺選擇了IBM的AS/400,才能選擇使用DB2數(shù)據(jù)庫管理系統(tǒng)。
4 MySQL
MySQL是當(dāng)今UNIX或Linux類服務(wù)器上廣泛使用的Web數(shù)據(jù)庫系統(tǒng)。也可以運(yùn)行于Windows平臺。它是一個多用戶、多線程、跨平臺的SQL數(shù)據(jù)庫系統(tǒng),同時是具有客戶/服務(wù)器體系結(jié)構(gòu)的分布式數(shù)據(jù)庫管理系統(tǒng),屬自由數(shù)據(jù)庫系統(tǒng),開放源代碼數(shù)據(jù)庫產(chǎn)品。
MySQL于1996年誕生于瑞典的TcX公司。其設(shè)計思想為快捷、高效、實(shí)用。雖然它對ANSI SQL標(biāo)準(zhǔn)的支持并不完善,但支持所有常用的內(nèi)容,迅裂完全可以勝任一般Web數(shù)據(jù)庫的工作。由于它不支持事務(wù)處理,MySQL的速度比一些商業(yè)數(shù)據(jù)庫塊2-3倍,并且MySQL還針對很多操作平臺做了優(yōu)化,完全支持多CPU系統(tǒng)的多線程方式。
在編程方面,MySQL也提供了C、C++、Java、Perl、Python和TCL等API接口,而且有MyODBC接口,任何可以使用ODBC接口的語言都可以使用它。
MySQL是中小企業(yè)網(wǎng)站Linux平臺的首選。MySQL在Linux下應(yīng)用較多,Linux+MySQL+PHP是基于Linux的更佳組合。由于屬開放源代碼自由軟件,性價比較高,是中小企業(yè)網(wǎng)站、個人頌蘆網(wǎng)站不錯的選擇。
怎樣在C語言中編寫多個程序并發(fā)執(zhí)行的程序
要實(shí)現(xiàn)完全的并發(fā)執(zhí)行,在一個CPU下實(shí)際上是不可能的
所說的并發(fā),都是在同一個時間段內(nèi)
多個任務(wù)開始,交判氏掘替占用CPU,最終結(jié)束。
也就是前一個任務(wù)還沒結(jié)束,后一個任掘核務(wù)就開始了,一種并發(fā)的形式而已。
所以 要么使用多線程
要核啟么 手動模擬這種多線程。
前者更常用。
多線程就可以
c 并發(fā)訪問數(shù)據(jù)庫的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于c 并發(fā)訪問數(shù)據(jù)庫,使用 C 實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的方法,大型網(wǎng)站數(shù)據(jù)庫系統(tǒng),怎么連接那么多并發(fā)數(shù)量的?,怎樣在C語言中編寫多個程序并發(fā)執(zhí)行的程序的信息別忘了在本站進(jìn)行查找喔。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
網(wǎng)站欄目:使用C實(shí)現(xiàn)并發(fā)訪問數(shù)據(jù)庫的方法(c并發(fā)訪問數(shù)據(jù)庫)
文章轉(zhuǎn)載:http://www.dlmjj.cn/article/dhgsjde.html


咨詢
建站咨詢
