沒有宮廷內鬥,數據庫界的延禧攻略
在數據庫領域也會有此類問題,老張我混跡開源數據庫圈多年。MySQL數據庫占領著開源數據庫的頭把交椅,MongoDB占領著NoSQL數據庫的第一位。我們來看下數據庫的整體排名情況;
兩者都是第一,所有總會拿來比較。也會經常被人問及到諸如此類的問題MongoDB4.0已經問世了,而且支持事務了,是不是將來可以取代MySQL了。MySQL和MongoDB哪個數據庫好用啊。今天老張想通過這篇文章,帶著大家全方位解讀MySQL與MongoDB的區別。讓有困惑的老鐵們明白,沒有誰替代誰,只有哪個場景更適合誰。
我們從下面四個方向依次闡明兩者的區別。只有更了解彼此,讓能更好地利用它們的功能性。
第一部分:數據庫概述
我們先來了解一下MySQL這個數據庫;
再來學習一下MySQL數據庫的特點;
MySQL了解完,同理我們來了解MongoDB及其特點的介紹;
MongoDB特點介紹:
學習完第一部分之後,我們對兩者數據庫都有了一定的認識;接下來去從運維的角度來檢驗兩者的不同;
第二部分:日常運維管理維度
1. 術語和概念的差異
結論可以看出,關系型數據庫中的表,在MongoDB中叫做集合。行在MongoDB中叫做文檔。所以經常管MongoDB叫做文檔型數據庫。
2.存儲數據結構的差異
在關系型數據庫中設計表,有些信息需要多表記錄。
而在MongoDB中,上面的三張表,就變成下面的這一段代碼就可以實現了。
{
_id:"M416",
name:"zhangsu",
phone:[1234,5678],
.....
}
MongoDB表設計的特點
- 數據聚合
- 數據嵌套
- 數組結構
3.啟動配置文件格式差異
MySQL數據庫的配置叫做my.cnf,我們來看下它的記錄方式;
[client]
port = 3306
socket = /data/mysql/mysql.sock
[mysql]
prompt="\u@db \R:\m:\s [\d]> "
no-auto-rehash
[mysqld]
user = mysql
port = 3306
basedir = /usr/local/mysql
datadir = /data/mysql/
socket = /data/mysql/mysql.sock
pid-file = db.pid
character-set-server = utf8mb4
skip_name_resolve = 1
open_files_limit = 65535
back_log = 1024
max_connections = 512
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
table_open_cache_instances = 64
thread_stack = 512K
external-locking = FALSE
max_allowed_packet = 32M
sort_buffer_size = 4M
join_buffer_size = 4M
thread_cache_size = 768
#query_cache_size = 0
#query_cache_type = 0
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
slow_query_log = 1
slow_query_log_file = /data/mysql/slow.log
log-error = /data/mysql/error.log
long_query_time = 0.1
server-id = 3306101
log-bin = /data/mysql/mybinlog
sync_binlog = 1
binlog_cache_size = 4M
max_binlog_cache_size = 1G
max_binlog_size = 1G
expire_logs_days = 7
master_info_repository = TABLE
relay_log_info_repository = TABLE
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates=1
binlog_format = row
relay_log_recovery = 1
relay-log-purge = 1
key_buffer_size = 32M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
#myisam_sort_buffer_size = 128M
#myisam_max_sort_file_size = 10G
#myisam_repair_threads = 1
lock_wait_timeout = 3600
explicit_defaults_for_timestamp = 1
innodb_thread_concurrency = 0
innodb_sync_spin_loops = 100
innodb_spin_wait_delay = 30
secure_file_priv=‘‘
super_read_only=0
transaction_isolation = REPEATABLE-READ
#innodb_additional_mem_pool_size = 16M
innodb_buffer_pool_size = 1024M
innodb_buffer_pool_instances = 8
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_data_file_path = ibdata1:100M:autoextend
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 32M
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_max_undo_log_size = 4G
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_flush_neighbors = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_purge_threads = 4
innodb_page_cleaners = 4
innodb_open_files = 65535
innodb_max_dirty_pages_pct = 50
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_checksum_algorithm = crc32
#innodb_file_format = Barracuda
#innodb_file_format_max = Barracuda
innodb_lock_wait_timeout = 10
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_file_per_table = 1
innodb_online_alter_log_max_size = 4G
internal_tmp_disk_storage_engine = InnoDB
innodb_stats_on_metadata = 0
innodb_status_file = 1
[mysqldump]
quick
max_allowed_packet = 32M
MongoDB配置文件使用Yaml格式
4.增刪改查操作的差異
5.事務支持的差異
但隨著MongoDB 4.0的問世,它將支持多文檔事務,屆時MongoDB將成為唯一能夠同時支持速度,靈活性,JSON文檔模型優勢 和ACID數據完整性保證的數據庫。
所謂的多文檔事務,可以理解為關系型數據庫的多行事務。在關系型的事務支持中,大家幾乎無一例外支持同一事務內操作的原子性,即要麽全部提交,要麽全部回滾。這個同一事務內可以有多個操作,針對於多個表,或者是同一個表內的多行數據。
總結:隨著事務支持的增加,MongoDB功能上更接近於關系型數據庫,但是和關系型還是有本質上的區別:MySQL是基於關系模型的數據庫,對各種數據多變的場景如物聯網或社交化並沒有MongoDB支持得好。MongoDB的JSON模型則具有動態靈活,數據庫無須下線就可以進行模式變遷升級,在這種場景下面,選擇MongoDB會特別合適。
6.備份上的差異
MySQL備份方式:
MongoDB備份方式:
邏輯備份與恢復
1.mongodump
2.mongorestore
3.mongoexport
4.mongoimport
註:MongoDB目前為止還沒有像xtrabackup這種好用的備份工具。所以一般來說,都是使用邏輯備份方式來進行操作
從運維角度我們對它們有了更深的認識之後,我們來從集群架構的維度出發,去探究其更深的不同之處。
第三部分:集群架構層面
1.集群架構層面上的差異
我們先從MySQL復制的角度入手;然後再介紹MySQL高可用集群架構
MySQL主從復制原理圖
MySQL復制種類總結;
異步復制:
通常沒說明指的都是異步,即主庫執行完Commit後,在主庫寫入Binlog日誌後即可成功返回客戶端,無需等Binlog日誌傳送給從庫,一旦主庫宕機,有可能會丟失日誌。
半同步復制:MySQL5.5版本之後引入了半同步復制功能,主從服務器必須同時安裝半同步復制插件,才能開啟該復制功能。在該功能下,確保從庫接收完主庫傳遞過來的binlog內容已經寫入到自己的relay log裏面了,才會通知主庫上面的等待線程,該操作完畢。如果等待超時,超過rpl_semi_sync_master_timeout參數設置的時間,則關閉半同步復制,並自動轉換為異步復制模式,直到至少有一臺從庫通知主庫已經接收到binlog信息了為止。
多源復制:
所謂多源復制,就是把多臺主庫的數據同步到一臺從庫服務器上,從庫會創建通往每個主庫的管道。在MySQL5.7之前的版本中,只能實現一主一從、一主多從或者多主多從的復制架構,如果想要實現多主一從的復制,只能使用MariaDB。MySQL 5.7版本已經可以實現多主一從的復制。
並行復制:
使用MySQL5.7的並行復制功能。在5.6版本中就有了並行的概念,但其中的並行復制是基於庫級別的,即slave_parallel_type=database。但在這種模式下,只是基於多庫少表的情況,並不適用於真實的生產環境下。在MySQL 5.7版本中,真正實現了基於組提交的並行復制,簡單說就是主庫並行執行SQL語句,從庫也可以通過多個workers線程並發執行relay log中主庫提交的事務。想要開啟MySQL5.7的並行復制可以在從庫設置參數slave_parallel_workers>0,並把5.7版本中新添加的slave_parallel_type參數設置為LOGICAL_CLOCK。該參數有DATABASE和 LOGICAL_CLOCK兩個值。MySQL5.6默認是database。
MySQL高可用集群架構分類圖;
MHA:
MHA的目的在於維持MySQL Replication中master庫的高可用性,其最大特點是可以修復多個slave之間的差異日誌,最終使所有slave保持數據一致,然後從中選擇一個充當新的master,並將其他slave指向它。當master出現故障時,可以通過對比slave之間I/O thread 讀取主庫binlog的position號,選取最接近的slave作為備選主庫(備胎)。其他的從庫可以通過與備選主庫對比生成差異的中繼日誌。在備選主庫上應用從原來master保存的binlog,同時將備選主庫提升為master。最後在其他slave上應用相應的差異中繼日誌並從新的master開始復制。
雙主+keepalived
中小型規模的時候,采用這種架構是最省事的。
兩個節點可以采用簡單的一主一從模式,或者雙主模式,並且放置於同一個VLAN中,在master節點發生故障後,利用keepalived/heartbeat的高可用機制實現快速切換到slave節點。
PXC集群:
PXC是基於Galera協議的MySQL高可用集群架構。Galera產品是以Galera Cluster方式為MySQL提供高可用集群解決方案的。Galera Cluster就是集成了Galera插件的MySQL集群。Galera replication是Codership提供的MySQL數據同步方案,具有高可用性,方便擴展,並且可以實現多個MySQL節點間的數據同步復制與讀寫,可保障數據庫的服務高可用及數據強一致性。
MGR架構:
MySQL官方在5.7.17版本正式推出組復制(MySQL Group Replication,簡稱MGR)。master1,master2,master3,所有成員獨立完成各自的事務。當客戶端先發起一個更新事務,該事務先在本地執行,執行完成之後就要發起對事務的提交操作了。在還沒有真正提交之前需要將產生的復制寫集廣播出去,復制到其他成員。如果沖突檢測成功,組內決定該事務可以提交,其他成員可以應用,否則就回滾。最終,這意味著所有組內成員以相同的順序接收同一組事務。因此組內成員以相同的順序應用相同的修改,保證組內數據強一致性。
接下來介紹MongoDB的復制情況;
MongoDB復制集:
三副本架構是最基礎的復制集的架構,一主兩備模式。主節點接受外界的讀寫請求,向備節點進行數據同步。當主節點宕掉,會自動切換到備節點,不影響線上業務,防止單點故障。
MongoDB復制集自動切換
副本集的所有成員都可以接受讀取操作。 但是,默認情況下,應用程序將其讀取操作指向primary。
副本集可以有至多一個primary節點,primary節點宕機後,集群會觸發選舉以選出新的primary節點
在以下三成員節點副本集架構中,primary宕機後,觸發了一次選舉,從剩下的兩個secondary節點裏,選舉出了一個新的primary節點。
MongoDB復制集讀寫分離設置
read preference 決定MongoDB客戶端從哪個節點上讀取數據。
默認情況下,應用程序將其讀取操作指向副本集中的primary節點。
指定read preference 選項時要註意:因為使用異步復制,復制延遲會導致secondary上的數據可能不是最新的。
默認情況下,復制集的所有讀請求都發到Primary,Driver可通過設置Read Preference來將讀請求路由到其他的節點。
primary: 默認規則,所有讀請求發到Primary
primaryPreferred: Primary優先,如果Primary不可達,請求Secondary
secondary: 所有的讀請求都發到secondary
secondaryPreferred:Secondary優先,當所有Secondary不可達時,請求Primary
nearest:讀請求發送到最近的可達節點上(通過ping探測得出最近的節點)
MongoDB分片架構
分片是一種在多臺機器上分配數據的方法。 MongoDB使用分片架構有助於您去管理非常大數量的數據集和高吞吐量操作的集群。
大數據量和高吞吐量的業務情況對單臺服務器來講是具備很大的挑戰性的。例如,高查詢率可能耗盡服務器的CPU容量。工作集大小超過系統內存,那麽壓力則會給到磁盤上,這對IO來講不是我們所希望看到的。
MongoDB支持通過分片進行水平縮放。
總結:MySQL的復制種類很多,集群架構在選擇性上來說也比較多。但橫向擴展能力上,沒有MongoDB的分片架構擴展能力強。
最後一部分,我們來通過MySQL與MongoDB的不同應用場景;來對兩種數據庫做一個最後的總結;
第四部分:應用場景角度
正如開篇介紹MySQL特點時說的,MySQL使用得覆蓋率已經接近100%。從大型BAT,電商平臺,遊戲公司,甚至諸多傳統行業也無不例外都在往MySQL數據庫方向靠攏,達到逐漸壟斷的趨勢。對於MongoDB 的應用也已經×××到各個領域,比如遊戲、物流、電商、內容管理、社交、物聯網、視頻直播等。
- 遊戲領域:遊戲場景,使用 MongoDB 存儲遊戲用戶信息,用戶的裝備、積分等直接以內嵌文檔的形式存儲,方便查詢、更新。
2.物流場景:使用MongoDB存儲訂單信息,訂單狀態在運送過程中會不斷更新,以MongoDB內嵌數組的形式來存儲,一次查詢就能將訂單所有的變更讀取出來。
3.社交場景:使用MongoDB存儲用戶信息,以及用戶發表的朋友圈信息,通過地理位置索引實現附近的人、地點等功能
4.物聯網場景:使用MongoDB存儲所有接入的智能設備信息,以及設備匯報的日誌信息,並對這些信息進行多維度的分析
對我而言,2009年開始接觸MySQL,我在2012年接觸的MongoDB的第一個版本2.1,對於這兩個數據庫真是手心手背都是肉。在我孤獨寂寞的時候,都是它們一直陪伴著我,感謝技術給我們帶來的簡單快樂。無論未來發展如何,沒有所謂的誰會替代誰,只是說它們各自都有不同的特點,促使在不同的應用場景下,我們使用誰更合適而已。這裏沒有宮廷內鬥,沒有爾虞我詐,只有那份最簡單地做技術的心,是現實版的延禧攻略!
對老張而言,寫篇文章很簡單,但真得希望可以幫助到那些剛入門或者想深入學習數據庫的同學們。能力有限,水平一般,哪裏有介紹不到的地方,還望大家海涵!
彩蛋
在我們最愛的51CTO 13歲生日之際,作為51CTO專家博主,數據庫專家,我推出了自己的訂閱專欄十年老兵教你練一套正宗的MySQL降龍十八掌,即日起,51CTO社區周年慶活動期間(2018.8.31截止),訂閱2個專欄,免費領取百元自選圖書一本>>>圖書自選傳送門
沒有宮廷內鬥,數據庫界的延禧攻略