當前位置:首頁 » 操作系統 » 資料庫線程

資料庫線程

發布時間: 2022-01-10 00:18:22

㈠ 請問mysql資料庫是不能多線程寫入嗎

在MySQL 8.0 之前, 我們假設一下有一條爛SQL,

mysqlselect * from t1 order by rand() ;

以多個線程在跑,導致CPU被跑滿了,其他的請求只能被阻塞進不來。那這種情況怎麼辦?


大概有以下幾種解決辦法:

  • 設置max_execution_time 來阻止太長的讀SQL。那可能存在的問題是會把所有長SQL都給KILL 掉。有些必須要執行很長時間的也會被誤殺。

  • 自己寫個腳本檢測這類語句,比如order by rand(), 超過一定時間用Kill query thread_id 給殺掉。

  • 那能不能不要殺掉而讓他正常運行,但是又不影響其他的請求呢?

    那mysql 8.0 引入的資源組(resource group,後面簡寫微RG)可以基本上解決這類問題。

    比如我可以用 RG 來在SQL層面給他限制在特定的一個CPU核上,這樣我就不管他,讓他繼續運行,如果有新的此類語句,讓他排隊好了。

    為什麼說基本呢?目前只能綁定CPU資源,其他的暫時不行。

    那我來演示下如何使用RG。

    創建一個資源組user_ytt. 這里解釋下各個參數的含義,

  • type = user 表示這是一個用戶態線程,也就是前台的請求線程。如果type=system,表示後台線程,用來限制mysql自己的線程,比如Innodb purge thread,innodb read thread等等。

  • vcpu 代表cpu的邏輯核數,這里0-1代表前兩個核被綁定到這個RG。可以用lscpu,top等列出自己的CPU相關信息。

  • thread_priority 設置優先順序。user 級優先順序設置大於0。

  • mysqlmysql> create resource group user_ytt type = user vcpu = 0-1 thread_priority=19 enable;Query OK, 0 rows affected (0.03 sec)


  • RG相關信息可以從 information_schema.resource_groups 系統表裡檢索。

  • mysqlmysql> select * from information_schema.resource_groups;+---------------------+---------------------+------------------------+----------+-----------------+| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY |+---------------------+---------------------+------------------------+----------+-----------------+| USR_default | USER | 1 | 0-3 | 0 || SYS_default | SYSTEM | 1 | 0-3 | 0 || user_ytt | USER | 1 | 0-1 | 19 |+---------------------+---------------------+------------------------+----------+-----------------+3 rows in set (0.00 sec)


  • 我們來給語句select guid from t1 group by left(guid,8) order by rand() 賦予RG user_ytt。

  • mysql> show processlist;+-----+-----------------+-----------+------+---------+-------+------------------------+-----------------------------------------------------------+| Id | User | Host | db | Command | Time | State | Info |+-----+-----------------+-----------+------+---------+-------+------------------------+-----------------------------------------------------------+| 4 | event_scheler | localhost | NULL | Daemon | 10179 | Waiting on empty queue | NULL || 240 | root | localhost | ytt | Query | 101 | Creating sort index | select guid from t1 group by left(guid,8) order by rand() || 245 | root | localhost | ytt | Query | 0 | starting | show processlist |+-----+-----------------+-----------+------+---------+-------+------------------------+-----------------------------------------------------------+3 rows in set (0.00 sec)


  • 找到連接240對應的thread_id。

  • mysqlmysql> select thread_id from performance_schema.threads where processlist_id = 240;+-----------+| thread_id |+-----------+| 278 |+-----------+1 row in set (0.00 sec)


  • 給這個線程278賦予RG user_ytt。沒報錯就算成功了。

  • mysqlmysql> set resource group user_ytt for 278;Query OK, 0 rows affected (0.00 sec)


  • 當然這個是在運維層面來做的,我們也可以在開發層面結合 MYSQL HINT 來單獨給這個語句賦予RG。比如:

  • mysqlmysql> select /*+ resource_group(user_ytt) */guid from t1 group by left(guid,8) order by rand()....8388602 rows in set (4 min 46.09 sec)


  • RG的限制:

  • Linux 平台上需要開啟 CAPSYSNICE 特性。比如我機器上用systemd 給mysql 服務加上

    systemctl edit mysql@80 [Service]AmbientCapabilities=CAP_SYS_NICE

  • mysql 線程池開啟後RG失效。

  • freebsd,solaris 平台thread_priority 失效。

  • 目前只能綁定CPU,不能綁定其他資源。

㈡ 如何在多線程操作資料庫

通常,最好避免鎖定 public 類型或鎖定不受應用程序控制的對象實例。例如,如果該實例可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。這可能導致死鎖,即兩個或更多個線程等待釋放同一對象。出於同樣的原因,鎖定公共數據類型(相比於對象)也可能導致問題。鎖定字元串尤其危險,因為字元串被公共語言運行庫 (CLR)「暫留」。這意味著整個程序中任何給定字元串都只有一個實例,就是這同一個對象表示了所有運行的應用程序域的所有線程中的該文本。因此,只要在應用程序進程中的任何位置處具有相同內容的字元串上放置了鎖,就將鎖定應用程序中該字元串的所有實例。因此,最好鎖定不會被暫留的私有或受保護成員。某些類提供專門用於鎖定的成員。例如,Array 類型提供 SyncRoot。許多集合類型也提供 SyncRoot。

java中如何用多線程訪問資料庫

//將資料庫中的數據條數分段 public void division(){ //獲取要導入的總的數據條數 String sql3="SELECT count(*) FROM [CMD].[dbo].[my1]"; try { pss=cons.prepareStatement(sql3); rss=pss.executeQuery(); while(rss.next()){ System.out.println("總記錄條數:"+rss.getInt(1)); sum=rss.getInt(1); } //每30000條記錄作為一個分割點 if(sum>=30000){ n=sum/30000; resie=sum%30000; }else{ resie=sum; } System.out.println(n+" "+resie); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }線程類public MyThread(int start,int end) { this.end=end; this.start=start; System.out.println("處理掉余數"); try { System.out.println("--------"+Thread.currentThread().getName()+"------------"); Class.forName(SQLSERVERDRIVER); System.out.println("載入sqlserver驅動..."); cons = DriverManager.getConnection(CONTENTS,UNS,UPS); stas = cons.createStatement(); System.out.println("連接SQLServer資料庫成功!!"); System.out.println("載入mysql驅動....."); Class.forName(MYSQLDRIVER); con = DriverManager.getConnection(CONTENT,UN,UP); sta = con.createStatement(); // 關閉事務自動提交 con.setAutoCommit(false); System.out.println("連接mysql資料庫成功!!"); } catch (Exception e) { e.printStackTrace(); } // TODO Auto-generated constructor stub } public ArrayList<Member> getAll(){ Member member; String sql1="select * from (select row_number() over (order by pmcode) as rowNum,*" + " from [CMD].[dbo].[my1]) as t where rowNum between "+start+" and "+end; try { System.out.println("正在獲取數據..."); allmembers=new ArrayList(); rss=stas.executeQuery(sql1); while(rss.next()){ member=new Member(); member.setAddress1(rss.getString("address1")); member.setBnpoints(rss.getString("bnpoints")); member.setDbno(rss.getString("dbno")); member.setExpiry(rss.getString("expiry")); member.setHispoints(rss.getString("hispoints")); member.setKypoints(rss.getString("kypoints")); member.setLevels(rss.getString("levels")); member.setNames(rss.getString("names")); member.setPmcode(rss.getString("pmcode")); member.setRemark(rss.getString("remark")); member.setSex(rss.getString("sex")); member.setTelephone(rss.getString("telephone")); member.setWxno(rss.getString("wxno")); member.setPmdate(rss.getString("pmdate")); allmembers.add(member); // System.out.println(member.getNames()); } System.out.println("成功獲取sqlserver資料庫數據!"); return allmembers; } catch (SQLException e) { // TODO Auto-generated catch block System.out.println("獲取sqlserver資料庫數據發送異常!"); e.printStackTrace(); } try { rss.close(); stas.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public void inputAll(ArrayList<Member> allmembers){ System.out.println("開始向mysql中寫入"); String sql2="insert into test.my2 values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; try { ps=con.prepareStatement(sql2); System.out.println("-------------------------等待寫入數據條數: "+allmembers.size()); for(int i=0;i<allmembers.size();i++){ ps.setString(1, allmembers.get(i).getPmcode()); ps.setString(2, allmembers.get(i).getNames()); //System.out.println(allmembers.get(i).getNames()); ps.setString(3, allmembers.get(i).getSex()); ps.setString(4, allmembers.get(i).getTelephone()); ps.setString(5, allmembers.get(i).getAddress1()); ps.setString(6, allmembers.get(i).getPmdate()); ps.setString(7, allmembers.get(i).getExpiry()); ps.setString(8, allmembers.get(i).getLevels()); ps.setString(9, allmembers.get(i).getDbno()); ps.setString(10, allmembers.get(i).getHispoints()); ps.setString(11, allmembers.get(i).getBnpoints()); ps.setString(12, allmembers.get(i).getKypoints()); ps.setString(13, allmembers.get(i).getWxno()); ps.setString(14, allmembers.get(i).getRemark()); //插入命令列表 //ps.addBatch(); ps.executeUpdate(); } //ps.executeBatch(); con.commit(); ps.close(); con.close(); this.flag=false; System.out.println(Thread.currentThread().getName()+"--->OK"); } catch (SQLException e) { // TODO Auto-generated catch block System.out.println("向mysql中更新數據時發生異常!"); e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub while(true&&flag){ this.inputAll(getAll()); } }

㈣ 資料庫執行sql是單線程還是多線程

單核單處理器,開一個線程跑循環輸出10萬條列印信息,開100個線程輸出10萬條列印信息.
後者比前者慢,因為輸出端是臨界資源,線程搶占的時間大,單線程則無需搶占!

㈤ 請教如何進行多線程連接資料庫並寫入數據

#include <QCoreApplication>
#include "thread.h"
#include <QVector>
#include <QDebug>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QVector<Thread*> vector;
Thread *thread;

//創建多個線程,並start
for(int i=0;i<10;i++){
thread=new Thread;
vector.append(thread);
thread->set(i);
thread->start();
}

//等待所有線程執行完,然後刪除線程
foreach(thread,vector){
thread->wait();
}
foreach(thread,vector){
delete thread;
}

return a.exec();
}

-------------------------------------------------------------------------------------------------

#include "thread.h"

Thread::Thread(QObject *parent) : QThread(parent)
{
}

void Thread::run()
{
begin();
}

//為每個線程創建一個連接名
void Thread::set(int a)
{
connectionName=QString::number(a);
}

void Thread::connectionDatabase(QString dbName)
{
QSqlDatabasedb=QSqlDatabase::addDatabase("QMYSQL",connectionName);
db.setHostName("localhost");
db.setDatabaseName(dbName);
db.setUserName("root");
db.setPassword("");

if(!db.open())
qDebug()<<"db open fail";
}

void Thread::begin()
{
QString dbName="learnsql";
connectionDatabase(dbName);

QSqlDatabase db=QSqlDatabase::database(connectionName);
db.transaction(); //開啟事物

QSqlQuery query(db);

//向表student中插入10000條數據
for(int i=1;i<=10000;i++){
query.exec("insert into student values(1)");
}

db.commit(); //提交事物
}

㈥ MYSQL資料庫如何多線程

1。通過線程的互斥來同步操作資料庫
2。資料庫採用事務處理表中的數據
3。採用共享方式打開資料庫,不是以獨占方式打開資料庫
建立一個mysql連接表加上一個
臨界區
,表結點是這樣的(mysqlcon,bool),根據實際情況定大小。我用的是10個連接。
當要進行mysql操作時,就從表中取出一個閑置的mysql連接,並把bool量改為true,使用完後改成false,臨界區的做用是保障一個mysql連接一次只能被一個線程使用。

㈦ mysql資料庫每次查詢是一條線程嗎

MySQL的查詢使用的是線程池。當有大量請求並發訪問時,一定伴隨著資源的不斷創建和釋放,導致資源利用率低,降低了服務質量。線程池技術,預先會創建一定數量的線程,當有請求達到時,線程池分配一個線程提供服務,請求結束後,該線程又去服務其他請求。 通過這種方式,避免了線程和內存對象的頻繁創建和釋放,降低了服務端的並發度,減少了上下文切換和資源的競爭,提高資源利用效率。在MySQL早期的版本中,處理連接的方式是One-Connection-Per-Thread,即對於每一個資料庫連接,MySQL-Server都會創建一個獨立的線程服務,請求結束後,銷毀線程。再來一個連接請求,則再創建一個連接,結束後再進行銷毀。但是,這種方式在高並發情況下,會導致線程的頻繁創建和釋放。當然,通過thread-cache,我們可以將線程緩存起來,以供下次使用,避免頻繁創建和釋放的問題,但是無法解決高連接數的問題。One-Connection-Per-Thread方式隨著連接數暴增,導致需要創建同樣多的服務線程,高並發線程意味著高的內存消耗,更多的上下文切換(cpu cache命中率降低)以及更多的資源競爭,導致服務出現抖動。相對於One-Thread-Per-Connection方式,一個線程對應一個連接,Thread-Pool實現方式中,線程處理的最小單位是statement(語句),一個線程可以處理多個連接的請求。這樣,在保證充分利用硬體資源情況下(合理設置線程池大小),可以避免瞬間連接數暴增導致的伺服器抖動。

㈧ 資料庫中事務、會話、線程這幾個概念是什麼關系

以下為個人理解,僅供參考:
1、會話可以創建多個事務
比如:使用客端連接資料庫,這樣你就可以執行很多個事務了

2、一個事務只能由一個會話產生
在資料庫里的事務,如果在執行的SQL都是由會話發起的,哪怕是自動執行的JOB也是由系統會話發起的

3、一個事務可能會產生一個或多個線程
比如RMAN備份,是可以創建多個線程可加快備份速度

4、一個線程在同一時間內只能執行一個事務
而一個線程,在沒結束當前事務是無法釋放資源來執行第二個事務

㈨ JAVA多線程訪問資料庫如何實現線程安全

你的提問就有問題
當你的程序不管是不是多線程的
獲得到一個資料庫連接是 資料庫會把這個連接標記為繁忙 當其他程序訪問時它會返回另外空閑的連接
連接個數是有限的 如果一直不釋放連接 資料庫就會告訴你連接已經使用完了
這里和線程安全有何關系呢? 線程安全和資料庫操作沒有直接關系

㈩ sql資料庫可以多線程查詢嗎

多線程操作,請確保每個線程操作的SQL語句中的表是相對獨立的。 不然,你需要安排線程間的順序,也就是lock代碼段。 同一時間,兩個線程一起跑同一句SQL,而且還操作同一張表,那麼,肯定就會有問題了。
一般這種是因為超出資料庫最大鏈接上限。再建立鏈接,不管緩存多少,會自動隊列消息等待。Timeout時間內沒有鏈接取消無法獲得鏈接許可權。可以將自己的資料庫鏈接個數設置大一些。

熱點內容
壓縮成iso文件 發布:2024-12-26 00:22:22 瀏覽:378
共軛復數的運演算法則 發布:2024-12-26 00:22:19 瀏覽:846
java視頻教程分享 發布:2024-12-26 00:22:18 瀏覽:427
web圖片緩存 發布:2024-12-26 00:21:01 瀏覽:156
verilog編譯結果 發布:2024-12-26 00:10:00 瀏覽:774
u盤啟動安裝linux系統 發布:2024-12-26 00:07:45 瀏覽:495
sizeof編譯 發布:2024-12-26 00:07:01 瀏覽:762
安卓手機什麼是雙卡 發布:2024-12-25 23:54:40 瀏覽:893
dnd伺服器ip地址 發布:2024-12-25 23:48:08 瀏覽:197
cad解壓沒有 發布:2024-12-25 23:48:03 瀏覽:15