勝者爲王,敗者爲寇這種思想好像從古代就一直延續到今日。非要分出個勝負,分出個誰好,誰壞才罷休。mysql
在數據庫領域也會有此類問題,我混跡開源數據庫圈多年。MySQL 數據庫佔領着開源數據庫的頭把交椅,MongoDB 佔領着 NoSQL 數據庫的第一位。sql
咱們來看下數據庫的總體排名狀況:數據庫
二者都是第一,因此總會拿來比較。也會常常被人問及到諸如此類的問題 MongoDB 4.0 已經問世了,並且支持事務了,是否是未來能夠取代 MySQL 了。數組
MySQL 和 MongoDB 哪一個數據庫好用?今天想經過這篇文章,帶着你們全方位解讀 MySQL 與 MongoDB 的區別。讓有困惑的老鐵們明白,沒有誰替代誰,只有哪一個場景更適合誰。bash
只有更瞭解彼此,才能更好地利用它們的功能性,下面我從四個方向依次闡明二者的區別:服務器
數據庫概述數據結構
咱們先來了解一下 MySQL 數據庫,以下圖:架構
接下來學習一下 MySQL 數據庫的特色,以下圖:併發
MySQL 瞭解完後,咱們再來了解 MongoDB 及其特色的介紹:運維
MongoDB 特色介紹,以下圖:
根據上文圖解,咱們對二者數據庫都有了必定的認識,接下來咱們從運維的角度來檢驗二者的不一樣。
平常運維管理維度
術語和概念的差別
從上圖能夠看出,關係型數據庫中的「表」,在 MongoDB 中叫作集合。「行」在 MongoDB 中叫作文檔。因此咱們管 MongoDB 叫作文檔型數據庫。
存儲數據結構的差別
在關係型數據庫中設計表,有些信息須要多表記錄。而在 MongoDB 中,上面的三張表,就變成下面的這一段代碼就能夠實現了。
{ _id:"M416", name:"zhangsu", phone:[1234,5678], ..... } 複製代碼
MongoDB 表設計的特色以下:
啓動配置文件格式差別
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 格式,以下圖:
增刪改查操做的差別
事務支持的差別
但隨着 MongoDB 4.0 的問世,它將支持多文檔事務,屆時 MongoDB 將成爲惟一可以同時支持速度,靈活性,JSON 文檔模型和 ACID 數據完整性保證的數據庫。
所謂的多文檔事務,能夠理解爲關係型數據庫的多行事務。在關係型的事務支持中,你們幾乎無一例外支持同一事務內操做的原子性,即要麼所有提交,要麼所有回滾。
這個同一事務內能夠有多個操做,針對於多個表,或者是同一個表內的多行數據。
總結:隨着事務支持的增長,MongoDB 功能上更接近於關係型數據庫,可是和關係型仍是有本質上的區別。
MySQL 是基於關係模型的數據庫,對各類數據多變的場景如物聯網或社交化並無 MongoDB 支持得好。
MongoDB 的 JSON 模型則具備動態靈活,數據庫無須下線就能夠進行模式變遷升級,在這種場景下面,選擇 MongoDB 會特別合適。
備份上的差別
MySQL備份方式,以下圖:
MongoDB備份方式(邏輯備份與恢復):
注:MongoDB 目前爲止尚未像 xtrabackup 這樣好用的備份工具。因此通常來講,都是使用邏輯備份方式來進行操做。
從運維角度咱們對它們有了更深的認識以後,咱們來從集羣架構的維度出發,去探究更深的不一樣之處。
集羣架構層面
集羣架構層面上的差別
咱們先從 MySQL 複製的角度入手,而後再介紹 MySQL 高可用集羣架構。
MySQL 主從複製原理圖以下:
MySQL 複製種類總結
異步複製:一般沒說明指的都是異步,即主庫執行完 Commit 後,在主庫寫入 Binlog 日誌後便可成功返回客戶端,無需等 Binlog 日誌傳送給從庫,一旦主庫宕機,有可能會丟失日誌。
半同步複製:MySQL 5.5 版本以後引入了半同步複製功能,主從服務器必須同時安裝半同步複製插件,才能開啓該複製功能。
在該功能下,確保從庫接收完主庫傳遞過來的 Binlog 內容已經寫入到本身的 Relay Log 裏面了,纔會通知主庫上面的等待線程,該操做完畢。
若是等待超時,超過 rpl_semi_sync_master_timeout 參數設置的時間,則關閉半同步複製,並自動轉換爲異步複製模式,直到至少有一臺從庫通知主庫已經接收到 Binlog 信息了爲止。
多源複製:所謂多源複製,就是把多臺主庫的數據同步到一臺從庫服務器上,從庫會建立通往每一個主庫的管道。
在 MySQL 5.7 以前的版本中,只能實現一主一從、一主多從或者多主多從的複製架構,若是想要實現多主一從的複製,只能使用 MariaDB。MySQL 5.7 版本已經能夠實現多主一從的複製。
並行複製:使用 MySQL 5.7 的並行複製功能。在 5.6 版本中就有了並行的概念,但它的並行複製是基於庫級別的,即 slave_parallel_type=database。在這種模式下,只是基於多庫少表的狀況,並不適用於真實的生產環境。
在 MySQL 5.7 版本中,真正實現了基於組提交的並行複製,簡單說就是主庫並行執行 SQL 語句,從庫也能夠經過多個 Workers 線程併發執行 Relay Log 中主庫提交的事務。
想要開啓 MySQL 5.7 的並行複製能夠在從庫設置參數 slave_parallel_workers > 0。
並把 5.7 版本中新添加的 slave_parallel_type 參數設置爲 LOGICAL_CLOCK。
該參數有 DATABASE 和 LOGICAL_CLOCK 兩個值。MySQL 5.6 默認是 DATABASE。
MySQL 高可用集羣架構
MySQL 高可用集羣架構分類圖以下:
MHA
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 來將讀請求路由到其餘的節點:
MongoDB 分片架構以下圖:
分片是一種在多臺機器上分配數據的方法。MongoDB 使用分片架構有助於您去管理很是大數量的數據集和高吞吐量操做的集羣。
大數據量和高吞吐量的業務狀況對單臺服務器來說是具有很大的挑戰性的。例如,高查詢率可能耗盡服務器的 CPU 容量。
工做集大小超過系統內存,那麼壓力會給到磁盤上,這對 IO 來說不是咱們所但願看到的。MongoDB 支持經過分片進行水平縮放。
總結:MySQL 的複製種類不少,集羣架構在選擇性上來講也比較多。但橫向擴展能力上,沒有 MongoDB 的分片架構擴展能力強。
最後,咱們經過 MySQL 與 MongoDB 不一樣的應用場景來對兩種數據庫作一個總結。
應用場景角度
正如開篇介紹 MySQL 特色時所說的,MySQL 使用得覆蓋率已經接近 100%。
從大型 BAT,電商平臺,遊戲公司,甚至諸多傳統行業也無不例外都在往 MySQL 數據庫方向靠攏,達到逐漸壟斷的趨勢。
對於 MongoDB 的應用也已經蔓延到各個領域,好比遊戲、物流、電商、內容管理、社交、物聯網、視頻直播等:
遊戲領域:使用 MongoDB 存儲遊戲用戶信息,用戶的裝備、積分等直接之內嵌文檔的形式存儲,方便查詢、更新。
物流場景:使用 MongoDB 存儲訂單信息,訂單狀態在運送過程當中會不斷更新,以 MongoDB 內嵌數組的形式來存儲,一次查詢就能將訂單全部的變動讀取出來。
社交場景:使用 MongoDB 存儲用戶信息,以及用戶發表的朋友圈信息,經過地理位置索引實現附近的人、地點等功能。
物聯網場景:使用 MongoDB 存儲全部接入的智能設備信息,以及設備彙報的日誌信息,並對這些信息進行多維度的分析。
我 2009 年開始接觸 MySQL,在 2012 年接觸 MongoDB 的第一個版本 2.1,對於這兩個數據庫真的是手心手背都是肉。
在我孤獨寂寞的時候,都是它們一直陪伴着我,感謝技術給咱們帶來的簡單快樂。
不管將來發展如何,沒有所謂的誰會替代誰,只是說它們各自都有不一樣的特色,促使在不一樣的應用場景下,咱們使用誰更合適而已。
這裏沒有宮廷內鬥,沒有爾虞我詐,只有那份最簡單地作技術的心,是現實版的《延禧攻略》!
張甦, 數據庫領域的專家和知名人士、圖書《MySQL王者晉級之路》做者,51CTO 專家博主。近 10 年互聯網線上處理及培訓經驗,專一於 MySQL 數據庫,對 MongoDB、Redis 等 NoSQL 數據庫以及 Hadoop 生態圈相關技術有深刻研究,具有很是豐富的理論與實戰經驗。
原文:http://database.51cto.com/art/201808/582300.htm