4.2-中間件之MySQL

4.2.1MySQL的基本知識

SQL語句

用于存取數據以及查詢、更新和管理關系數據庫系統。包括:DQL(select)、DML(insert,update,delete)、DDL(create,alter,drop)、DCL(grant,revoke)權限驗證。

MySQL體系結構

MySQL內部分層。

在最外層是server層,有幾個組件組成。其中SQL Interface用于對用戶發送來的sql進行詞法句法分析,生成語法樹。再由Parser對語法樹進行過濾,比如要查詢的字段在表中沒有,進行報錯。過濾后,由Optimizer制定執行計劃,選擇一個最佳的執行方案執行sql

在server層執行后,是存儲引擎層,用于具體執行server層傳入的執行方案。常用的存儲引擎是InnoDB。

在存儲引擎層下面,是文件系統層,存儲著物理數據。

MySQL內部連接池

mysql會為每一個連接分配一個線程,每一個線程以阻塞io的方式進行read、do_command,各線程的處理是并發的。

MySQL執行一條select語句的過程

在網絡層面,連接器接收連接,為連接分配線程。再先查詢緩存(mysql8.0后已經刪除這一步),若緩存沒有啊,通過SQL Interface分析器組件進行詞法句法分析生成語法樹,再通過優化器組件制定執行方案,執行器根據執行計劃,從存儲引擎獲取數據返回。

如果是預處理語句,比如有很多select,就可以寫成select? * from user where id?= ?;?用來接收參數,避免重復解析。會跳過連接器、分析器、優化器,直接進入到執行器執行計劃這一步。

數據庫設計的三范式

目的:避免數據冗余、允許空間占用

三范式內容:每一個列的字段,都是最簡的,不可再分的。如果有多個主鍵,那么表中其他鍵都需要完全依賴主鍵,且與主鍵直接相關,而不是間接相關。如果某表不能滿足上述要求,那么說明表中有冗余數據存在,需要對表進行拆分,以編號替代冗余部分。

反范式:范式可以簡單理解為 “時間換空間”,犧牲多張表跳轉查詢的時間來避免數據冗余空間浪費。但是如果冗余字段較少且追求查詢效率,可以用反范式。

MySQL刪除數據的幾種方式

1.drop(DDL):完全刪除表,包括數據和結構,表將不存在,不可回滾

2.truncate(DDL):只刪除表中數據,變成空表,其中自增約束置為初始值。不可回滾,以頁為單位刪除

3.delete(DML):刪除部分或全部數據,可以回滾,以行為單位刪除。

MySQL的高級查詢

1.分組+聚合查詢:通過group by對表分組后,計算sum()、avg()、max()、min()、count(),都是對分組后的各組內進行操作。

比如:select? `gender`,count(*) as num from `student` group by `gender`;

2.聯表查詢??

舉例:查詢 ‘數學’課程比‘語文’課程成績高的所有學生的學號;

分析:涉及兩張表,一個是分數表,一個是課程表。需要先從課程表中,通過課程名稱cname = '數學' 查詢出課程對應的cid,然后再到分數表中查詢對應課程的學生id以及分數num,這樣就構成了兩個表A與B,分別意味著報了數學的集合,報了語文的集合,表中只有兩個字段:sid與num。

再通過inner join取兩張表的交集,即數學語文都報了的人,構成一張新表,最后select 數學分數高于語文分數的學生學號即可。

select A.student_id from(select student_id,num from score where course_id =(select cid from course where cname = `數學`)) as Ainner join(select student_id,num from score where course_id =(select cid from course where cname = `語文`))as Bon A.student_id = B.student_idwhere A.num > B.num;如果沒報語文課程的人也算在內,那就改成left join最后一行改成where A.num > IFNULL(B.num,0);

視圖是什么?

是一種虛擬存在的表,是一個邏輯表,其內容由查詢定義,本身并不包含數據。

優點:向上面例子中的表構建比較麻煩,如果每次都要寫這么多sql很冗余,可以直接構建一個視圖,且視圖的結構不會受原表的影響。

4.2.2MySQL索引原理以及SQL優化

索引是什么?

索引是一種有序的數據結構,按照單個或者多個列的值進行排序,用于提升搜索的效率。比如主鍵索引(非空+唯一)、唯一索引(可空)、普通索引(可空+可不唯一),組合索引(對表中多個列進行索引)。

索引常用的數據結構是B+樹:

在course表中的主鍵索引cid,作用就相當于一個map<int , course>,根據cid找到course,其中索引cid就是聚集索引B+樹中的非葉子節點,用于查找,葉子節點中存儲的就是course(數據)+cid(索引)

在course表中的普通索引tid,作用就相當于一個 multimap<int ,pairs<int,int>> ,根據tid找到鍵值對 <索引信息,主鍵信息>。其中索引tid就是輔助索引B+樹中的非葉子節點,用于查找,葉子節點中存儲的就是索引信息 + 主鍵信息,要拿到完整的數據要拿到主鍵信息,再到聚集索引B+樹中取出。但是如果要查詢的信息只有主鍵信息,或者其他輔助索引B+樹中本身就有的信息,則為覆蓋查詢,可以直接返回,速度很快,這也是不建議用select *,而具體寫出字段名的原因,可以避免回表查詢。

主鍵的選擇

有設置primary key則當然其為主鍵;如果沒設置則選一個非空唯一索引作為主鍵;如果非空唯一索引也沒有,則創建一個6字節的_rowid作為主鍵。

MySQL是磁盤IO,索引如何保證業務高效?

1.葉子節點的連續

在通過非葉子索引節點查找到目標數據所在的頁后,由于葉子節點間是有序且直接連接的,可以減少磁盤的尋道時間,直接把頁從磁盤讀入內存。

2.一次從磁盤中讀取多個頁到內存中緩存

對B+樹的操作,也不會馬上寫回磁盤,對于change buffer,會定期合并到buffer pool中,而buffer pool中的被修改后的臟數據,會集中direct io到磁盤中

MySQL的內存安全保證

在MySQL對磁盤的操作,如果是操作的聚集索引B+樹,則是先對buffer pool中的節點進行操作,如果操作的是輔助索引B+樹,則是對Change buffer中的節點操作。但是如果出現斷電,也不用擔心內存數據丟失,沒有及時刷盤導致數據錯誤,因為有Redo Log,aof型日志,記錄buffer中的變化信息,可以恢復buffer。

組合索引在查詢時候的規則:最左匹配原則

組合索引算作輔助索引。

如果將兩個索引(A,B)結合成一個索引,那么在select查詢的時候,會按照最左匹配原則進行查詢,即select中有沒有where帶上A的相關限定信息,如果有,則會按照其進行排序,如果沒有或者只有B的限定信息,則會進行全表查詢。

索引下推是什么?

對象是輔助索引,普通索引和聯合索引場景居多。

原本是在server層獲得存儲引擎層的數據后,根據索引條件過濾數據

索引下推機制,即將部分索引條件判斷下推到存儲引擎中過濾數據,最終返回給server層。

索引的作用是加速sql執行,有沒有索引失效的情況?

1.select ... where A and B 若A和B中,有一個字段不是索引,則會索引失效

2.如果讓索引字段參與運算,則會索引失效,如? where cid -1 = 2;

3.like 模糊查詢,以 %開頭,會進行全表查詢,索引失效,因為B+樹讀取到%不知道怎么查。

4.沒有遵循最左匹配原則

出現了sql比較慢的排查思路

先開啟慢查詢日志,找到SQL語句,然后通過explain字段,通過分析器看where、group by、order by后面的字段有沒有踩索引,如果沒有,看看是沒有創建索引還是索引失效。如果有踩索引但是速度慢,看看能否用in 或者 not in優化成聯表查詢,或者如果SQL語句太大了,考慮拆分,減少聯合查詢。

4.2.3MySQL事務原理

事務的特性和Redis中的事務有共同性,也是在有多條連接的情況下,利用事務性保證單個連接上用戶操作的不可分割。只需要在多條sql前加上 begin; 末尾加上 commit;事務的特征有:

1.原子性:undolog輔助實現原子性

2.一致性:數據庫的一致性:用戶處理完后比如有唯一約束的字段也不能出現重復的值。

? ? ? ? ? ? ? ? 邏輯的一致性:沒有臟讀、幻讀、不可重復讀的問題。

3.隔離性:指并發連接間的隔離性,適當的破壞一致性。有四個隔離級別,對應著四種并發程度。

4.持久性:redolog實現持久性

四個隔離級別(由低到高)

1.讀未提交:對讀操作不做任何處理,對寫操作自動加鎖

分析:存在臟讀問題。A事務寫還未結束,B事務因為讀無限制,看到A事務的中間結果,為臟讀。

2.讀已提交(RC):讀操作采用MVCC策略。讀到的是最新的數據,寫操作自動加鎖

分析:避免了臟讀,A沒有結束,B讀不到他修改的結果。但是存在“不可重復讀”問題,A事務要是在B事務結束前結束了,那么B事務會看到最新的結果,即兩次B事務中的查詢結果不一致。

3.可重復讀(RR):讀操作采用MVCC策略。讀到的是事務開始前版本的數據,寫操作自動加鎖

分析:避免了不可重復讀問題,兩次查詢的結果都是一樣的。但是存在“幻讀”問題,A事務和B事務都在執行過程中,B事務查詢到沒有ID為3的行數據,但緊接著A事務插入了一個ID為3的行數據,那么B事務在插入ID為3的行數據的時候,就會因為違反唯一約束而返回錯誤。

4.可串行化:讀寫都加鎖

分析:解決了幻讀的問題,即在B事務查詢是否有ID為3的行數據的時候,加上for update字段(x鎖)或者lock in share mode(S鎖/共享鎖)加鎖,這時候A事務想要添加ID為3的行數據會阻塞,知道B事務添加ID為3的行數據并且commit后,A事務會報錯。

MVCC策略

MVCC的核心思想:不加鎖,為每行數據保存多個版本(快照)。當一個事務需要讀取數據時,MVCC會提供一個符合該事務開始時間點的“數據快照”,而不是直接讀取當前最新的、可能正在被其他事務修改的數據。?? 這樣就實現了讀不加鎖,讀寫操作通常不會互相阻塞,極大地提升了并發性能。

Read View是事務在進行快照讀(普通SELECT語句)時產生的數據結構,它定義了當前事務能看到哪個版本的數據。
“讀已提交RC”是在每次讀取數據的時候,生成新的read_view

“可重復讀RR”是在啟動事務的時候,生成新的read view,一直使用到事務提交或者回滾

read view中有trx_id 、min_trx_id 、max_trx_id 、m_ids,事務間可見的情況只有:

trx_id < min_trx_id? ?和? min_trx_id < trx_id < max_trx_id && trx_id 不屬于 m_ids

事務隔離級別的實現

利用鎖機制實現,鎖的類型有:行級鎖(共享鎖、排他鎖),表級鎖(意向共享鎖、意向排他鎖)。

鎖算法有:Record記錄鎖(單個行記錄上的鎖),Gap間隙鎖(鎖定一個范圍,全開區間),Next-Key Lock(記錄所 + 間隙鎖,左開右閉)

鎖的對象:在RC和RR兩種隔離級別下

1.行級鎖是針對表的索引加鎖,包括聚合索引和輔助索引

2.表級鎖是針對頁或者表進行加鎖

3.Gap鎖通常是加在RR隔離級的情況下

舉例:

聚集索引,查詢命中,RC和RR兩種隔離級別都會對命中行加鎖。

聚集索引,查詢未命中,RC不加鎖,RR在未命中字段的左右區間加一個gap鎖

輔助非唯一索引,查詢命中,RC把輔助表命中的行鎖定,并且把聚合數據表中相關的行也鎖定。

RR在RC的基礎上,還在輔助表中,命中的兩個字段,產生的三個間隙,都加gap鎖。

死鎖的產生

情況1:相同表不同行加鎖順序相反,比如A事務update id1 id2? ,B事務update id2 id1;update和delete操作是會自動加上鎖的。解決:調整執行順序。

情況2:鎖沖突,在RR隔離級別下面,如果先持有了gap鎖,再想加意向鎖,就會產生鎖沖突。解決:降為RC隔離級別,這樣就沒有gap鎖了。

4.2.4MySQL緩存策略

在MySQL中,也會采用緩存,不同于buffer pool,而是一種類似Redis的內存緩存,他不僅有更快的速度,而且不像buffer pool受限于MySQL,雖然緩存中的數據必須在MySQL中存在,但是可以根據業務自定義熱點數據存入緩存。可以大大降低數據庫的壓力,對寫壓力沒有什么緩解,因為如果頻繁寫的話,我們用一個緩存還需要多考慮一致性的問題。

弊端是redis不支持事務的回滾,不能rollback,還有就是存在緩存和MySQL不一致的可能。

在引入Redis緩存后的寫操作如何實現?

1.追求安全

在每次DML寫操作,都先在Redis緩存中,刪除對應的行(比如要修改 id = 1的年齡,先在緩存中刪除id =1的行數據)。然后再到MySQL中進行操作,操作后,利用一個偽裝從數據庫的節點,從MySQL中拉取數據到Redis緩存中。這樣可以保證在修改期間,其余用戶不會讀到臟數據,但是在修改前還要額外操作緩存影響效率。

2.追求效率

DML操作也對Redis執行,但是加上一個pexpire,設置過期時間如200ms,這樣緩存中id=1的年齡就先被修改,隨后再修改MySQL中id=1的年齡。如果MySQL中修改失敗,那么Redis在200ms后也會刪除這個錯誤的數據,如果MySQL成功,那么就會通過偽造從數據庫進行數據同步。

此處的過期時間實際上 = MySQL傳輸時間 + MySQL處理時間 + MySQL同步時間

在這個期間內,別的用戶可能會讀到Redis中的臟數據。

MySQL到Redis的同步是如何實現的?

1.修改配置文件使transfer工具與MySQL和Redis建立連接。

2.配置熱點數據,只拉取熱點數據表的內容

3.用lua腳本設定同步的規則:怎么把MySQL的結構改成Redis的結構?transfer工具啟動連接到MySQL的bin.log文件,按行讀取里面的內容,改成Hash結構。獲取各列的字段值,設置key后再通過Redis中的命令將各值直接HSET寫入key對應的value。

還有哪些方式能提升MySQL的訪問性能?

1.讀寫分離

MySQL也有很多salve從數據庫用作備份,他們會不斷的主動讀取主數據庫的二進制log,保持數據一致性。這樣我們可以將業務的DML操作交給主數據庫,而讀操作提交給從數據庫,分擔主數據庫的讀壓力。但是從數據庫讀取的數據沒有強一致性,會有延遲存在,如果有強一致性需求,需要從主數據庫讀取。

2.數據庫連接池

MySQL內部用的是select,阻塞io模型,一個連接對應一個線程,所以我們可以開啟數據庫連接池創建多條連接,提升并發度

3.異步連接

MySQL是阻塞IO,只會一個請求一個請求的執行,但是在服務器端我們可以設置非阻塞io,不斷的給MySQL發請求,不等他連接后再發下一個。節省網絡傳輸時間,解放服務器端核心線程。

MySQL緩存可能遇到的問題:都是源于大量請求進入到MySQL

1.緩存穿透

如果持續訪問Redis和MySQL中都不存在的的數據,造成MySQL性能急劇下降

解決:

(1)對目標訪問的數據在Redis中設置對應的key,nil;避免其再進一步訪問MySQL

(2)在Redis上配置布隆過濾器,他能判斷訪問的數據是否在MySQL數據庫中,如果不在拒絕訪問

2.緩存擊穿

比如在百億秒殺開始前1s,Redis中的熱點數據過期了,那么大量的訪問就會并發進入到MySQL,造成MySQL性能急劇下降

解決:

(1)設置熱點數據不過時

(2)設置分布式鎖,訪問Redis發現數據不存在的請求,先獲取分布式鎖(例如使用Redis的?SETNX?命令),成功獲取的線程才能訪問MySQL,這樣獲得鎖的線程就能重建緩存,其他等待的線程也能從緩存中獲取數據。

3.緩存雪崩

Redis中大量的key在同一時間內過期,大量的請求也就無法命中,導致MySQL的壓力過大。相比較于緩存擊穿的范圍更大

解決:

(1)間隔設置過期時間

(2)在重啟系統或者流量低峰期將高頻訪問的數據預熱到緩存中

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

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

相關文章

LVS + Keepalived 高可用負載均衡集群

目錄 一、核心組件與作用 1. LVS&#xff08;Linux Virtual Server&#xff09; 2. Keepalived 二、DR 模式下的 LVS Keepalived 工作原理 1. 整體架構 2. 數據包流向&#xff08;DR 模式&#xff09; 三、部署步驟&#xff08;DR 模式&#xff09; 3.1 環境規劃 3.2…

知識沉淀過于碎片化如何形成體系化框架

要將過于碎片化的知識沉淀轉變為體系化的框架&#xff0c;必須采取一套自上而下設計與自下而上歸集相結合的系統性方法&#xff0c;其核心路徑在于首先進行戰略性診斷與頂層藍圖設計、其次構建統一且可擴展的知識架構&#xff08;分類與標簽體系&#xff09;、然后實施系統性的…

XLua教程之C#調用Lua

上一篇文章 XLua教程之入門篇-CSDN博客 在C#腳本中訪問lua全局數據&#xff0c;特別是table以及function&#xff0c;代價比較大&#xff0c;建議盡量少做相關操作。 LuaEnv.Global.Get 用于獲取一個全局變量&#xff0c;但是無法獲取局部變量(用local修飾) 全局基本類型變量…

C++ 標準庫中的哈希函數:從std::hash到自定義哈希器

C 標準庫中的哈希函數&#xff1a;從 std::hash 到自定義哈希器 1. 引言 在上一篇中&#xff0c;我們介紹了哈希表為什么能夠實現 O(1) 查找。 核心秘密在于&#xff1a;哈希函數。 在 C 標準庫中&#xff0c;哈希表容器&#xff08;如 unordered_map、unordered_set&#xff0…

在圖形 / 游戲開發中,為何 Pixels Per Unit(PPU)數值越小,物體在屏幕上顯示的尺寸越大?

1. 什么是 PPU&#xff1f; PPU&#xff08;Pixels Per Unit&#xff09;指的是 多少像素對應游戲世界中的一個單位&#xff08;Unit&#xff09;。 在 Unity 等游戲引擎中&#xff0c;1 Unit 通常被視為世界空間的基本長度&#xff0c;比如 1 米。2. PPU 與物體大小的關系PPU …

【ZYNQ開發篇】Petalinux和電腦端的靜態ip地址配置

使用Petalinux工具為ZYNQ板卡搭建嵌入式Linux操作系統&#xff0c;成功搭建后&#xff0c;用戶通常會使用客戶端軟件對ZYNQ板卡上的Linux系統進行訪問&#xff0c;軟件需要知道ZYNQ板卡的ip地址才能進行訪問&#xff0c;如果ip地址是動態變化的&#xff0c;軟件每次訪問都要重新…

AVL樹知識總結

AVL樹概念性質一顆AVL樹或是空樹&#xff0c;或者具有一下性質的二叉搜索樹&#xff1a;左右都是AVL樹&#xff0c;左右子樹高度差的絕對值不超過1AVL樹有n個結果&#xff0c;高度保持在O&#xff08;logN&#xff09; 搜索時間復雜度O(logN&#xff09;模擬實現插入定義&#…

返利app的跨域問題解決方案:CORS與反向代理在前后端分離架構中的應用

返利app的跨域問題解決方案&#xff1a;CORS與反向代理在前后端分離架構中的應用 大家好&#xff0c;我是阿可&#xff0c;微賺淘客系統及省賺客APP創始人&#xff0c;是個冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在返利APP的前后端分離架構中&#xff0c;跨…

【dl】python基礎 深度學習中需要用到的python基礎

直接在jupyter寫筆記然后導出md格式真的太好用了本文筆記來自小破站視頻BV1K14y1c75ePython 基礎 1. 變量 1.1 三種基本變量類型 # 字符串 str str_v "123"# 數字 int或float num_v 11 float_v 12.0# 布爾型 bool bool_v True1.1.1 字符串 f字符串&#xff1a;在…

Vue FullPage.js 完整使用指南:Vue 3 官方全屏滾動解決方案

概述 vue-fullpage.js 是 FullPage.js 的官方 Vue.js 3 包裝器&#xff0c;為 Vue 3 應用提供了強大的全屏滾動功能。該插件基于成熟的 FullPage.js 庫&#xff0c;支持多種滾動效果和豐富的配置選項&#xff0c;特別適用于企業級數據大屏、產品展示、單頁應用等場景。 官方信…

軟件工程實踐一:Git 使用教程(含分支與 Gitee)

文章目錄目標一、快速上手1. Windows 安裝 Git2. 初始化 / 克隆二、核心概念速覽三、常用命令清單1) 查看狀態與差異2) 添加與提交3) 歷史與回溯4) 撤銷與恢復&#xff08;Git 2.23 推薦新命令&#xff09;5) 忽略文件四、分支與合并&#xff08;Branch & Merge&#xff09…

css`min()` 、`max()`、 `clamp()`

min() 用來計算多個數值中最小的那個&#xff0c;非常適合做自適應。 width: min(50vw, 500px) 50vw 表示 視口寬度的 50% 500px 表示 500px min(50vw, 500px) 表示會取兩者中 最小的那個 作為最終的寬度&#xff0c;。 使用場景 限制某個元素寬度不超過某個值&#xff1b; 響…

【WRF-VPRM 預處理器】HEG 安裝(服務器)-MRT工具替代

目錄 HEG 安裝 驗證 HEG 安裝與否 設置環境變量(建議) 命令行接口(Command Line Interface) hegtool 工具 hegtool 用法 Header File 格式 功能1:`gdtif` 工具 – MISR 數據處理 `gdtif` 使用方式 參數文件格式(Parameter File Format) 功能2:`resample` 工具 – 重采樣…

PyTorch 神經網絡

神經網絡是一種模仿人腦神經元鏈接的計算模型&#xff0c; 由多層節點組成&#xff0c; 用于學習數據之間的復雜模式和關系。神經網絡通過調整神經元之間的連接權重來優化預測結果&#xff0c;這個過程可以涉及到向前傳播&#xff0c;損失計算&#xff0c;反向傳播和參數更新。…

詳細解析蘋果iOS應用上架到App Store的完整步驟與指南

&#x1f4f1;蘋果商店上架全流程詳解 &#x1f469;?&#x1f4bb;想要將你的App上架到蘋果商店&#xff1f;跟隨這份指南&#xff0c;一步步操作吧&#xff01; 1?? 申請開發者賬號&#xff1a;訪問蘋果開發者網站&#xff0c;注冊并支付99美元年費&#xff0c;獲取開發者…

三維GIS開發實戰!Cesium + CZML 實現火箭飛行與分離的 3D 動態模擬

CZML是一種基于JSON的數據格式&#xff0c;專門用于在Cesium中描述3D場景和時間動態數據。本文將詳細介紹了CZML的特點&#xff08;JSON格式、時間動態性、層次結構等&#xff09;和基本組件&#xff0c;并給出了一個火箭發射的實例。通過搭建Cesium開發環境&#xff08;使用vi…

Spring Boot 深入剖析:BootstrapRegistry 與 BeanDefinitionRegistry 的對比

在 Spring Boot 的啟動過程中&#xff0c;BootstrapRegistry 和 BeanDefinitionRegistry 是兩個名為“Registry”卻扮演著截然不同角色的核心接口。理解它們的差異是深入掌握 Spring Boot 啟動機制和進行高級定制開發的關鍵。BootstrapRegistry public static ConfigurableAppl…

貪心算法應用:速率單調調度(RMS)問題詳解

Java中的貪心算法應用&#xff1a;速率單調調度(RMS)問題詳解 1. 速率單調調度(RMS)概述 速率單調調度(Rate Monotonic Scheduling, RMS)是一種廣泛應用于實時系統中的靜態優先級調度算法&#xff0c;屬于貪心算法在任務調度領域的經典應用。 1.1 基本概念 RMS基于以下原則&…

Cesium4--地形(OSGB到3DTiles)

1 OSBG OSGB&#xff08;OpenSceneGraph Binary&#xff09;是基于 OpenSceneGraph&#xff08;OSG&#xff09; 三維渲染引擎的二進制三維場景數據格式&#xff0c;廣泛用于存儲和傳輸傾斜攝影測量、BIM、點云等大規模三維模型&#xff0c;尤其在國產地理信息與智慧城市項目中…

多語言共享販賣機投資理財共享售賣機投資理財系統

多語言共享販賣機投資理財/共享售賣機分紅/充電寶/充電樁投資理財系統 采用thinkphp內核開發&#xff0c;支持注冊贈金、多級分銷&#xff0c;功能很基礎 修復后臺用戶列表管理 可自定義理財商品 多種語言還可以添加任意語言 源碼開源 多級分銷 注冊贈金等