1. MySQL 存儲引擎
1.1. 存儲引擎和 MySQL
MySQL 提供並維護多個存儲引擎,每個引擎具有不同的特徵和含義。創建表時可以選擇特定存儲引擎, MySQL 使用InnoDB 存儲引擎在硬盤上爲該表創建存儲。可以選擇替代存儲引擎來用於每個表。通常,根據哪些存儲引擎可以提供最適合您的應用程序需求的功能來做出此選擇。每個存儲引擎具有一組特定運行特徵。這些特徵包括用於管理查詢爭用的鎖的類型以及該存儲引擎是否支持事務。這些引擎屬性對查詢處理性能、併發性以及死鎖預防具有一定影響。
雖然可以使用許多其他存儲引擎,但對於大多數用例, InnoDB 都是最適合的。
MySQL 提供以下存儲引擎:
² InnoDB
² MyISAM
² MEMORY
² ARCHIVE
² FEDERATED
² EXAMPLE
² BLACKHOLE
² MERGE
² NDBCLUSTER
² CSV
還可以使用第三方存儲引擎。
MySQL 提供並維護多個存儲引擎。 MySQL 服務器還可以與許多第三方存儲引擎兼容。 MySQL 存儲引擎是數據庫服務器內的低級別引擎,它負責存儲和檢索數據,並且可以通過內部 MySQL API 進行訪問,在某些情況下,可以由應用程序直接訪問。請注意,一個應用程序可以在任何給定時間使用多個存儲引擎。幻燈片中列出了當前支持的存儲引擎。
請注意, InnoDB 和 NDBCLUSTER 是具有事務性的唯一兩個 MySQL 存儲引擎。
第三方引擎具有不同的源和功能, MySQL 不技術支持這些引擎。有關這些引擎的進一步信息、文檔、安裝指南、錯誤報告或任何幫助或協助,請直接與該引擎的開發人員聯繫。有關第三方存儲引擎的簡要論述,請參見以下鏈接中的“ Other Storage Engines (其他存儲引擎)”文檔:
http://dev.mysql.com/doc/refman/5.6/en/storage-engines-other.html 。
有關 MySQL 存儲引擎的更多信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/storage-engines.html 。
1.2. 顯示存儲引擎設置
使用 SELECT 確認會話存儲引擎:
SELECT @@default_storage_engine;
使用 SHOW 確認每個表的存儲引擎:
SHOW CREATE TABLE City\G
SHOW TABLE STATUS LIKE 'CountryLanguage'\G
使用 INFORMATION_SCHEMA 確認每個表的存儲引擎:
SELECT TABLE_NAME, ENGINE FROM
INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'City'
AND TABLE_SCHEMA = 'world_innodb'\G
1.3. 設置存儲引擎
在啓動配置文件中設置服務器存儲引擎:
[mysqld]
default-storage-engine=<Storage Engine>
使用 SET 命令爲當前客戶機會話設置:
SET @@storage_engine=<Storage Engine>;
使用 CREATE TABLE 語句指定:
CREATE TABLE t (i INT) ENGINE = <Storage Engine>;
如果創建表時沒有使用 ENGINE 選項顯式指定存儲引擎, MySQL 服務器使用默認引擎創建該表,該引擎由 storage_engine系統變量的值給定。可以通過使用 SET 命令在會話級別覆蓋服務器默認值。
1.4. InnoDB 存儲引擎
InnoDB 是 MySQL 的默認存儲引擎,提供高可靠性和高性能以及下面的主要優點:
² 事務安全(遵從 ACID )
² MVCC ( Multi-Versioning Concurrency Control ,多版本併發控制)
² 表數據進行整理來優化基於主鍵的查詢
² 支持外鍵引用完整性約束
² 大型數據捲上的最大性能
² 將對錶的查詢與不同存儲引擎混合
² 出現故障後快速自動恢復
² 用於在內存中緩存數據和索引的緩衝區池
任何其他磁盤相關的關係數據庫引擎很難比得上 InnoDB 的效率。下面介紹使用 InnoDB 的一些其他優點:
事務安全 :通過事務提交、回滾以及用於保護用戶數據的故障恢復功能,可以實現 ACID 遵從性。
外鍵支持 :包括級聯刪除和更新。
恢復和備份 :支持一致而聯機的邏輯備份。
混合查詢 :在同一語句內,可以將 InnoDB 表與來自其他 MySQL 存儲引擎的表混合。例如,可以使用 join 運算在單個查詢中合併來自 InnoDB 和 MEMORY 表的數據。
全文索引 :可以在文本列中有效地搜索單詞或短語。
有關 InnoDB 存儲引擎功能的更多信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html 。
InnoDB 作爲默認存儲引擎內置到 MySQL 服務器中,新表的默認存儲引擎是 InnoDB 。使用 ENGINE=<Storage Engine> 等子句創建或更改表時選擇替代存儲引擎。
1.4.1 InnoDB 功能
功能 | 支持 | 功能 | 支持 |
存儲限制 | 64 TB | 索引高速緩存 | 是 |
MVCC | 是 | 數據高速緩存 | 是 |
B 樹索引 | 是 | 自適應散列索引 | 是 |
羣集索引 | 是 | 複製 [ c ] | 是 |
壓縮數據 | 是 [ a ] | 更新數據字典 | 是 |
加密數據 [ b ] | 是 | 地理空間數據類型 | 是 |
查詢高速緩存 | 是 [ c ] | 地理空間索引 | 否 |
事務 | 是 | 全文搜索索引 | 是 |
Lock 粒度 | 行 | 羣集數據庫 | 否 |
外鍵 | 是 | 備份和恢復 [ c ] | 是 |
文件格式管理 | 是 | 快速索引創建 | 是 |
多個緩衝區池 | 是 | PERFORMANCE_SCHEMA | 是 |
更改緩衝 | 是 | 自動故障恢復 | 是 |
注意:
[a] 需要 InnoDB Barracuda 文件格式。
[b] 在服務器中(通過加密功能)而不是在存儲引擎中實現。
[c] 在服務器中而不是在存儲產品中實現。使用 MEB 進行備份時例外,其不是在服務器級別進行。
有關這些功能的更多信息,請參見 MySQL 術語詞彙表,網址爲:
http://dev.mysql.com/doc/refman/5.6/en/glossary.html 。
有關 InnoDB 功能的完整信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html 。
1.4.2 將現有錶轉換爲 InnoDB
使用 ALTER TABLE 更改引擎是一項成本很高的操作,因爲它在內部將所有數據從一個引擎複製到另一個引擎。建議不要將mysql 數據庫(例如 user 或 host )中的 MySQL 系統錶轉換爲 InnoDB ,系統表使用 MyISAM 引擎,此操作不受支持。轉換方法如下:
方法一:使用 ALTER TABLE 更改存儲引擎
ALTER TABLE t ENGINE = InnoDB;
方法二:從其他存儲引擎克隆表,例如使用相同定義創建空 InnoDB 表,創建適當的索引,然後插入行
INSERT INTO <innodb_table> SELECT * FROM<other_table>;
創建作爲使用其他存儲引擎的表的克隆的 InnoDB 表時,還可以在插入數據後創建索引。要更好地控制插入過程,您可以小塊形式插入大型表:
INSERT INTO newtable SELECT * FROM oldtable
WHERE yourkey > something AND yourkey <= somethingelse;
注:插入了所有記錄後,可以重命名錶。
在轉換大型表的過程中,增加 InnoDB 緩衝區池的大小來減少磁盤 I/O 。還可以增加 InnoDB 日誌文件的大小。第一次啓動MySQL 服務器並且啓用 InnoDB 時,最好從命令提示符運行 MySQL 服務器 mysqld ,而不是從 mysqld_safe 運行或者作爲Windows 服務運行。
有關涉及的步驟,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-init.html 。
1.4.3 InnoDB 系統表空間
默認情況下, InnoDB 元數據、撤消日誌和緩衝區存儲在系統“表空間”中。這是單個邏輯存儲區域,可以包含一個或多個文件。每個文件可以是常規文件或原始分區。最後的文件可以自動擴展。 InnoDB 使用兩個主要的基於磁盤的資源來運行:
表空間 :在單個邏輯存儲區域中存儲表內容(數據行)和索引
日誌文件 :記錄回滾和恢復的事務活動
InnoDB 在表空間中存儲數據、索引、元數據、日誌和緩衝區。默認情況下,數據和索引存儲在基於表的表空間中。 InnoDB使用共享表空間來包含元數據、撤消日誌、更改緩衝區以及兩次寫緩衝區。
共享表空間可以佔用多個文件。可以將共享表空間中的最後一個文件配置爲自動擴展,在這種情況下,如果表空間裝滿,InnoDB 會自動擴展該表空間。
默認情況下,共享表空間還包含回滾段。事務修改行時,將在回滾段中存儲撤消日誌信息。此信息用於回滾失敗的事務。通過將 innodb_undo_logs 選項設置爲非零值並配置 innodb_undo_tablespaces 的值,來將回滾段移出共享表空間。
1.4.4 InnoDB 數據表空間
除了系統表空間之外, InnoDB 還在數據庫目錄中創建另外的表空間,用於每個 InnoDB 表的 .ibd 文件。 InnoDB 創建的每個新表在數據庫目錄中設置一個 .ibd 文件來搭配表的 .frm 文件。 .ibd 文件用作表自己的表空間文件, InnoDB 存儲表內容和索引。
基於表的表空間(獨立表空間)支持表壓縮、支持空間回收(通過 TRUNCATE )、– 支持動態行格式;
使用共享表空間的好處是移除大量數據的語句使用較少文件系統開銷,例如 DROP TABLE 或 TRUNCATE TABLE ,同時避免冗餘臨時數據文件。另外,共享表空間包含 InnoDB 數據字典和回滾段,可以使用 innodb_file_per_table 選項控制此設置。如果不想將數據存儲在基於表的表空間中,可以通過使用 skip_innodb_file_per_table 選項或者將 innodb_file_per_table 選項設置爲OFF 來將數據存儲在共享數據庫中。禁用該選項不會影響已經創建的任何 InnoDB 表的可訪問性。仍然可以訪問這些表。
同一數據庫也可以不同表混合使用不同的表空間類型。更改該設置僅會更改已創建的新表的默認值,或者已更改來將引擎設置爲 InnoDB 的表(甚至已經在使用 InnoDB 的表)的默認值。
1.4.5 Innodb 表空間目錄結構
除了其表空間文件, InnoDB 存儲引擎還管理一組特定於 InnoDB 的日誌文件,其中包含關於正在進行的事務的信息。客戶機執行事務時,其進行的更改存放在 InnoDB 日誌 (ib_logfile) 中。最新日誌內容緩存在內存中。通常,緩存的日誌信息會在事務提交時寫入並刷新到磁盤上的日誌文件中,雖然也可能提前發生該操作。
1.4.6 共享表空間配置
共享表空間通過添加數據文件增加表空間大小。如果命名了多個數據文件,則通過分號 (;) 符號分隔這些文件。增加 InnoDB系統表空間的一種更容易(但是不太可取)的方式是從一開始就將其配置爲自動擴展。在表空間定義中指定最後一個數據文件的autoextend 屬性。然後, InnoDB 在用完空間時會以 64 MB 增量自動增加該文件的大小。可以通過設置innodb_autoextend_increment 系統變量的值來更改該增量大小,以 MB 爲單位。如果使用關鍵字 autoextend 定義了最後一個數據文件,重新配置表空間的過程必須考慮最後一個數據文件已經增長到的大小。獲取數據文件的大小,將其向下舍入到 1024 ×1024 字節 (= 1 MB) 的最近倍數,並在 innodb_data_file_path 中顯式指定舍入的大小。然後,可以添加其他數據文件(使用尚不存在的文件名)。
在 my.cnf 文件中使用 innodb_data_file_path 選項。
[mysqld]
innodb_data_file_path=datafile_spec1[;datafile_spec2]...
示例 :創建一個表空間,其中包含一個名爲 ibdata1 且大小爲 50 MB (固定)的數據文件和一個名爲 ibdata2 且大小爲 50 MB(自動擴展)的數據文件:
[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
默認情況下將文件放置在 data 目錄中。如果需要,顯式指定文件位置。
請記住,僅 innodb_data_file_path 中的最後一個數據文件可以指定爲自動擴展。
有關 InnoDB 配置參數的更多信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html 。
1.4.7 日誌文件和緩衝區
A. 日誌文件
客戶機執行事務時,其進行的更改存放在 InnoDB 日誌中。最新日誌內容緩存在內存中(日誌緩衝區)。緩存的日誌信息會在事務提交時寫入並刷新到磁盤上的日誌文件中,雖然也可能提前發生該操作。
如果修改表時發生故障,將使用日誌文件進行自動恢復。 MySQL 服務器重新啓動時,它會重新應用日誌中記錄的更改,以確保表中反映所有已提交事務。有關更改 InnoDB 日誌文件的數量和大小的信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-data-log-reconfiguration.html 。
B. 緩衝區
InnoDB 維護其自己的緩衝區池以在主內存中緩存常用的數據和索引。 InnoDB 在表空間中存儲其表和索引。 InnoDB 表可以非常大,甚至在文件大小限制爲 2 GB 的操作系統上也是如此。可以啓用多個緩衝區池來最大程度地降低爭用。此高速緩存應用於如此多種類型的信息並且將處理速度提高如此多,您應該將多達 80% 的數據庫服務器的物理內存分配給 InnoDB 緩衝區池。
如果未指定 InnoDB 配置選項,則 MySQL 在 MySQL 數據目錄中創建一個名爲 ibdata1 且大小爲 10 MB 的自動擴展數據文件以及名爲 ib_logfile0 和 ib_logfile1 且大小爲 5 MB 的兩個日誌文件。要獲得良好性能,您應該指定顯式 InnoDB 參數。
配置緩衝區池以獲得良好性能
MySQL 使用多個緩衝區池來改進大型緩衝區池(通常爲多 GB 範圍)的性能。
InnoDB 緩衝區池很大時,可以從內存(而不是硬盤)快速檢索許多數據請求。 MySQL 使用多個緩衝區池實例來最大程度地降低線程之間的爭用。存儲在緩衝區池中或者從緩衝區池讀取的每個頁將基於散列值分配給一個緩衝區池。每個緩衝區池管理其自己的數據。使用散列函數將緩衝區池中的每個頁隨機分配給一個緩衝區池。每個緩衝區池管理其自己的空閒列表、刷新列表、LRU 以及連接到緩衝區池的所有其他數據結構,並由其自己的緩衝區池互斥鎖進行保護。
默認情況下, MySQL 配置八個緩衝區池實例(除了在 32 位 Windows 系統上)。要更改此設置,請將innodb_buffer_pool_instances 配置選項設置爲從 1 (最小值)到 64 (最大值)的一個值。僅當將 innodb_buffer_pool_size 設置爲大小爲 1 GB 或更大時,此選項才生效。您指定的總大小在所有緩衝區池之間分割。您應指定 innodb_buffer_pool_instances和 innodb_buffer_pool_size 的組合,從而每個緩衝區池實例至少爲 1 GB 。
在啓動時預裝入緩衝區池來提高性能,請啓用選項:
– innodb_buffer_pool_load_at_startup
– innodb_buffer_pool_dump_at_shutdown
1.4.8 NoSQL 和 Memcached API
InnoDB 支持具有集成的 Memcached 守護進程的插件,其在相同進程空間中運行,從而以較低開銷進行高效數據通信。對於某些操作,通過使用較簡單的 Memcached API (基於文本的協議和二進制協議),而不是使用 SQL 層,您的應用程序可以在提交 SQL 語句時繞過所需的解析和優化階段,並避免檢查強類型數據的開銷。此類型的應用程序稱爲 NoSQL ( Not Only SQL ,不僅僅是 SQL )。
除了傳統的 Memcached 環境(其在重新啓動 Memcached 時會丟失鍵 / 值存儲), InnoDB 集成表示您可以將 Memcached存儲配置爲持久存儲到 InnoDB 。因爲 InnoDB 支持該存儲,所以您可以受益於 InnoDB 的其他功能,例如緩衝數據訪問和故障恢復。這意味着您可以使用內存存儲的 Memcached 存儲(由強大而持久的 InnoDB 表支持)來獲得速度和簡化。
您仍可以通過 SQL 訪問基礎表以進行報告、分析、即席查詢、批量載入、集合運算(例如並集和交集)以及非常適合於 SQL的表達性和靈活性的其他運算(例如彙總和聚合)。因爲 Memcached 消耗相對較少的 CPU 並且易於控制其內存容量,所以可以與 MySQL 實例在同一系統上一起順利運行。
1.4.8.1. 配置 Memcached
A. 配置 Memcached 表
MySQL>SOURCE <MYSQL_HOME>/scripts/innodb_memcached_config.sql
或者
MySQL>SOURCE /usr/share/mysql/innodb_memcached_config.sql
innodb_memcached_config.sql 腳本設置 Memcached 配置數據庫及其表。默認 InnoDB 後備存儲是 test 數據庫中的demo_test 表。可以通過修改 innodb_memcache 數據庫中的容器表來更改此項。
innodb_memcache 數據庫,其包含下列表:
l cache_policies :存放每個 Memcached 操作的後備存儲策略;本地 RAM 高速緩存、 InnoDB 或兩者
l Containers :存放用作 Memcached 後備存儲的每個 InnoDB 表的配置
l config_options :存放 separator 和 table_map_delimiter 配置選項的值
test 數據庫,其包含下列表: demo_test
B. 安裝 Memcached 插件:
INSTALL PLUGIN daemon_memcached SONAME "libmemcached.so";
該插件啓用許多可配置變量。要查看 Memcached 配置變量,請發出以下命令:
SHOW VARIABLES LIKE 'daemon_memcached%';
例如,以下參數配置 Memcached 插件的行爲:
l daemon_memcached_enable_binlog :啓用 Memcached 操作的二進制日誌記錄,其允許複製 Memcached API 操作。
l daemon_memcached_r_batch_size :控制讀取批處理大小,出於性能考慮。
l daemon_memcached_w_batch_size :控制寫入批處理大小。默認值爲 1 ,所以會立即提交每個 Memcached 寫入操作
C. 配置 Memcached 變量:
– daemon_memcached_option :在啓動時傳遞給 Memcached 守護進程的空格分隔的選項
1.4.8.2. Memcached 的鍵 / 值數據
Memcached 協議支持 add 、 delete 、 set 、 get 、 incr 和 decr 等操作。
l 每個操作處理高速緩存中的鍵 / 值對。
鍵和值作爲字符串來傳遞。鍵不能包含空格、回車符、換行符、製表符等空白字符。鍵類似於表中的主鍵,值類似於同一表中的另一列。
l 高速緩存是平面名稱空間。
確保每個鍵都是唯一的。例如,如果您提供其他表中的鍵 / 值,則在鍵前面附加該表名稱。
l 值可以是簡單字符串(或存儲爲字符串的數值)或序列化複雜數據。
使用 Memcached 的主要好處是讀取或寫入鍵 / 值數據時效率較高。在概念上,這類似於一個包含兩列的表,其中鍵列是主鍵(因此是唯一的)。鍵和值存儲爲字符串,由於 Memcached 協議的性質,鍵值不能包含空格或換行符。
對於鍵 / 值查找, Memcached 插件使用的直接低級別數據庫訪問路徑比等效 SQL 查詢高效得多。
值存儲爲字符串,可以表示簡單值,例如數值、字符串或已經序列化的複雜值(即,置於可以重新構造原始指針和嵌套的文本形式)。必須在 API 接口的 Memcached 外部執行此序列化(例如,通過在代碼中實現 Java Serializable 接口)或者通過將複雜數據格式化爲 JSON 或 XML 。
類似地,必須在訪問 memcached 表的 SQL 語句中將簡單數值從字符串轉換爲數值(例如,通過使用 CAST() 函數)。
1.4.8.3. 將 NoSQL 用於 MySQL 數據庫
使用 InnoDB 表作爲 Memcached 操作的容器(後備存儲)。要從 Memcached 獲得最大好處,請將其用作快速鍵 / 值訪問方法,並使用 InnoDB 後備存儲。 Memcached 協議不支持簡單聚合、聯接數據或 SQL 協議支持的其他功能。使用 InnoDB 表作爲 Memcached 鍵 / 值對的容器,您可以運行功能強大的 SQL 語句,來執行使用 Memcached 協議創建和修改的數據分組、聚合和聯接。
鍵和值是字符串。鍵最大大小爲 250 字節。對於更長的鍵:將鍵值散列到小於 250 字節的值,爲 Memcached 鍵重新配置允許的大小;
通過指定不同類的 Memcached 數據來使用多個 InnoDB 表作爲 Memcached 容器。在 containers 表中配置此項。例如,以get @@newcontainer 形式發出 Memcached 請求,將後續請求重定向到名爲“ newcontainer ” 的容器。
使用 innodb_memcache.containers 表可以配置一個或多個 InnoDB 表來用作 Memcached 後備存儲。指定容器表的名稱、模式和鍵列、值、標誌以及其他設置。每個容器具有一個 Memcached 名稱,可以用來標識 Memcached 操作的容器。操作定位於名爲“ default ” 的容器,直到被要求更改容器。
/usr/share/mysql/innodb_memcached_config.sql 文件創建和填充 innodb_memcache.containers 表,是配置容器的很好示例。
1.4.9 引用完整性
將相關的數據分割到單獨表中時,可以使用主鍵和外鍵來加強表關係。一個表的主鍵被另一個表中的鍵引用,引用鍵稱爲外鍵,每個表都需要主鍵。
INSERT 到輔助表(而沒有指向主表的外鍵)不會完成。通過在聯接的列上使用外鍵將提高 JOIN 性能。 UPDATE 或DELETE 數據時,可以使用 CASCADE 選項自動更新或刪除輔助表中的任何相關數據。
使用外鍵:
l 通過使用最常查詢的列爲每個表指定主鍵,如果沒有明顯主鍵則指定自動增量值。
l 可以嘗試將數據插入在主表中沒有相應數據的輔助表,但是其返回錯誤且插入失敗。
l 爲了獲得快速聯接性能,在聯接列上定義外鍵,並在每個表中使用相同數據聲明這些列。如果您啓用 CASCADE 選項,外鍵將刪除或更新傳播到所有受影響的表,並且當父表中沒有相應列時禁止在子表中插入數據。
在 City 表中指定主鍵的示例:
CREATE TABLE City (
ID int(11) NOT NULL AUTO_INCREMENT,
Name char(35) NOT NULL DEFAULT '',
CountryCode char(3) NOT NULL DEFAULT '',
District char(20) NOT NULL DEFAULT '',
Population int(11) DEFAULT NULL,
PRIMARY KEY (ID),
KEY CountryCode (CountryCode),
CONSTRAINT city_ibfk_1 FOREIGN KEY (CountryCode) REFERENCES country (Code)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1
1.4.10 多版本控制
多版本控制保存關於已更改行的舊版本的信息,支持併發和回滾等事務功能,並使用稱爲回滾段的數據結構在表空間中存儲信息。
回滾段是包含撤消日誌的存儲區域,其默認情況下是系統表空間的一部分。 InnoDB 使用回滾段中的信息執行事務回滾中所需的撤消操作。它還使用該信息來構建行的早期版本以實現一致讀取。在內部向數據庫中存儲的每行添加三個字段:
DB_TRX_ID :六個字節的字段,指示插入或更新該行的最後一個事務的事務標識符。此外,刪除在內部被視爲更新處理,其中設置行的特殊位來將其標記爲刪除。
DB_ROLL_PTR :稱爲滾動指針的七個字節的字段。它指向寫入回滾段的撤消日誌記錄。如果更新了行,撤消日誌記錄包含重建行被更新前的內容所需的信息。
DB_ROW_ID :包含行 ID 的六個字節的字段,隨着插入新行而單調增加。如果 InnoDB 自動生成羣集索引,該索引包含行ID 值。否則, DB_ROW_ID 列不顯示在任何索引中。
如果在表中按相同速度以小批量插入和刪除行,清除線程會滯後,表會因爲所有“死”行而變得越來越大,使所有操作受到磁盤限制並且非常慢。在這種情況下,通過使用 innodb_max_purge_lag 系統變量限制新行操作並向清除線程分配更多資源。
1.4.11 Lock
InnoDB Lock 無需設置鎖即可實現一致讀取。對 DML 語句使用行級別 Lock ,從不提升鎖,死鎖的等待圖形檢測。
InnoDB 具有下列一般 Lock 屬性:
l InnoDB 無需設置鎖即可實現一致讀取,因爲它使用多版本控制,從而不需要鎖。修改行的事務可以查看其自己版本的那些行,撤消日誌使其他事務可以查看原始行。要強制 SELECT 語句 Lock 數據,可以向該語句添加 Lock 修飾符。
l 需要鎖時, InnoDB 使用行級別 Lock 。與多版本控制一起,這將產生良好的查詢併發性,因爲給定表可以由不同客戶機同時讀取和修改。
l InnoDB 在發現需要鎖時可以獲取行鎖。從不通過將鎖轉換爲頁鎖或表鎖來提升該鎖。這樣可以最大程度降低鎖爭用,提高併發性(雖然其對 DDL 操作使用表級別 Lock )。
l 可能會出現死鎖,因爲 InnoDB 在事務過程中直到需要鎖時才獲取鎖。 InnoDB 可以刪除死鎖並回滾一個事務來解決死鎖。
l 失敗的事務最終開始超時, InnoDB 將回滾這些事務。
有關死鎖的更多信息,請參見 MySQL 術語詞彙表,網址爲:
http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_deadlock 。
1.4.12 Next-Key Lock
InnoDB 使用一種稱爲 Next-Key Lock 的算法,其使用行級別 Lock ,搜索 / 掃描表索引並在索引記錄上設置共享鎖或互斥鎖;
Next-Key Lock 會影響索引記錄前面的“間隙”,即新索引記錄無法正好插在 Lock 記錄前面。
Gap Lock 可防止出現“幻影問題”。在下面的示例中,第一個事務 Lock 大於 10 的任何值,即使該值不存在也是如此:
事務 1 :
SELECT c FROM t WHERE c > 10 FOR UPDATE;
事務 2 :
INSERT INTO t(c) VALUES (50);
InnoDB 將一種稱爲 Next-Key Lock 的算法用於行級別 Lock 。按以下方式執行 Lock :搜索或掃描表的索引時,會在遇到的索引記錄上設置共享鎖或互斥鎖。因此,行級別鎖實際是索引記錄鎖。 InnoDB 在索引記錄上設置的 Next-Key Lock 會影響索引記錄前面的“間隙”。如果用戶在索引中的記錄上具有共享鎖或互斥鎖,其他用戶無法按索引順序正好在 Lock 記錄前面(間隙)插入新記錄。
執行此間隙的 Next-Key Lock 可以防止所謂的幻影問題。同一查詢在不同時間產生不同行集時,事務內會出現幻影問題。例如,如果 SELECT 執行兩次,但第二次返回的行不是第一次返回的行,該行是“幻影”行。
1.4.13 非 Lock 一致性讀取
時間 | 會話 1 | 會話 2 |
| | s1> START TRANSACTION; | s2> START TRANSACTION; |
| | | s1> SELECT * FROM t; Empty Set | |
| | s2> INSERT INTO t VALUES (1, 2); | |
| V | s1> SELECT * FROM t; Empty Set | |
| | s2> COMMIT; | |
| | | s1> SELECT * FROM t; | |
| | s1> COMMIT; | |
| V | s1> SELECT * FROM t; |
一致讀取表示 InnoDB 使用多版本控制對您的查詢提供某個時間點的數據庫快照。您的查詢看見在時間點之前提交的事務所進行的更改,不會看見後面或未提交事務進行的更改。示例中,僅當會話 2 已提交了插入並且會話 1 也已提交(從而時間點超過會話 2 的提交)時,會話 1 纔看見會話 2 插入的行。如果要查看數據庫的“最新”狀態,請使用 READ COMMITTED 隔離級別或Lock 讀取。
1.4.14 減少死鎖
要減少死鎖的可能性,請使用事務,而不是 LOCK TABLE 語句:
l 將插入或更新數據的事務保持足夠小(很少行數),從而其不會保持打開狀態很長時間。經常提交事務。
l 不同的事務更新多個表或大範圍的行時,在每個事務中使用相同順序的操作(例如, SELECT ... FOR UPDATE )。
l 在 WHERE 子句中使用的列上創建索引。
不要設置隔離級別以避免死鎖,此操作沒有作用,因爲隔離級別更改讀取操作的行爲,而死鎖是由於寫入操作而出現的,與讀取操作無關。
如果事務由於死鎖而失敗則重新發出該事務。死鎖並不危險,只需要重試。另外,按固定順序訪問表和行,或者向表添加精心選擇的索引也有助於減少死鎖。
如果出現死鎖, InnoDB 會檢測到該情況並回滾一個事務(犧牲者)。因此,即使您的應用程序邏輯完全正確,您仍須處理必須重試事務的情況。要監視死鎖出現的頻率(以及許多其他 InnoDB 統計信息),請使用 SHOW ENGINE INNODB STATUS 命令:
mysql> SHOW ENGINE INNODB STATUS\G
=====================================
110222 16:54:12 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 5 seconds
...
1.4.15 外鍵 Lock
創建表時添加外鍵約束:
CREATE TABLE City (
...
CountryCode char(3) NOT NULL DEFAULT '',
...
KEY CountryCode (CountryCode),
CONSTRAINT city_ibfk_1 FOREIGN KEY
(CountryCode) REFERENCES country (Code)
...
約束就是在表中的一個或多個列值上放置的限制,從而積極強制執行完整性規則。約束使用索引來實現。如果在表上定義了外鍵約束,將在用於引用外鍵約束的插入、更新或刪除操作中的任何記錄上放置共享記錄級別鎖。 InnoDB 在約束失敗的情況下也設置這些鎖。
InnoDB 逐行檢查外鍵約束。執行外鍵檢查時, InnoDB 在其必須查看的子或父記錄上設置共享行級別鎖。 InnoDB 立即檢查外鍵約束;該檢查不會延遲到事務提交時。示例顯示 City 表的 CountryCode 列與 Country 表的 Code 列相關。對任一列的任何更改都受到此關係的約束。
有關外鍵約束的更多信息,請參見《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html 。
1.5. MyISAM 存儲引擎
MyISAM 存儲引擎將磁盤上的每個表存儲在三個文件中( .frm 、 .MYD 和 .MYI )並具有以下功能:
l 支持 FULLTEXT 搜索和空間數據類型
l 靈活的 AUTO_INCREMENT
l 壓縮式只讀表,可以節省空間
l 表級別 Lock 來管理查詢之間的爭用
l 可移植存儲格式
l 可以指定表的行數
l 可以控制非唯一索引的更新以便將數據載入到空表中
在 MySQL 服務器版本 5.5.5 之前, MyISAM 是默認 MySQL 存儲引擎。當前默認是 InnoDB 存儲引擎。 mysql 數據庫包含MyISAM 格式的表。
每個 MyISAM 表由三個文件表示:
l 格式文件: 存儲表結構的定義 (mytable.frm)
l 數據文件: 存儲錶行的內容 (mytable.MYD)
l 索引文件: 存儲表上的所有索引 (mytable.MYI)
其他功能:
l MyISAM 表佔用的空間非常小。
l 表存儲格式是可移植的,所以表文件可以直接複製到其他主機並由該主機上的服務器使用。
l 將數據載入到空表中時,可以禁用非唯一索引的更新,然後在載入數據後重新啓用。
l MyISAM 支持幾何空間擴展。
l MyISAM 可以通過將表大小限制爲特定數量的行來提高性能。
有關 MyISAM 存儲引擎功能的更多信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html 。
1.6. MEMORY 存儲引擎
MEMORY 存儲引擎使用內存中存儲的、通過 .frm 文件表示在磁盤上的內容創建表。
它具有以下功能:
l 表數據和索引存儲在內存中
l 由於是內存中存儲所以具有很高性能
l 固定長度行存儲格式
l 重新啓動後表內容將丟失
l 最大大小選項 --max-heap-table-size
l 表級別 Lock
MEMORY 表:
l 不能包含 TEXT 或 BLOB 列
l 可以針對不同的列使用不同字符集
l 每個表通過數據庫目錄中的 .frm 格式文件表示在磁盤上。
l 服務器重新啓動後內容將丟失(結構存在,但是表包含零行)。
l MySQL 使用表級別 Lock 管理查詢爭用。不會出現死鎖。
HEAP 可能仍舊以舊 SQL 代碼顯示, MySQL 服務器仍舊可識別 HEAP 以實現向後兼容。處理更新時, MEMORY 性能受到由於單線程執行所導致的爭用和表鎖開銷的約束。這限制了負載增加時的可伸縮性,特別是對於包括寫入的語句混合情況。此外,MEMORY 在服務器重新啓動過程中不保留表內容。
MEMORY 是有效且有用的存儲引擎,對於設計用來提高性能以及滿足特定業務規則的幾乎所有應用,應該考慮該引擎。
有關 MEMORY 存儲引擎功能的更多信息,請參閱《 MySQL 參考手冊》:
http://dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html 。
1.7. ARCHIVE 存儲引擎
ARCHIVE 存儲引擎用於以壓縮格式存儲大量數據從而佔用非常少的資源。它具有下列主要特徵:
l 由 .frm 文件表示
l 數據文件: .ARZ
l 不支持索引
l 支持 INSERT 和 SELECT ,但不支持 DELETE 、 REPLACE 或 UPDATE
l 支持 ORDER BY 操作和 BLOB 列
l 接受除空間數據類型之外的所有數據類型
l 使用行級別 Lock
l 支持 AUTO_INCREMENT 列
鄭州婦科醫院:http://jbk.39.net/yiyuanzaixian/sysdfkyy/
1.8. BLACKHOLE 存儲引擎
BLACKHOLE 存儲引擎充當“黑洞” ,其接受數據,但是將其丟棄而不存儲。此存儲引擎具有下列主要特徵:
l 由 .frm 文件表示
l 用於複製
l 支持所有種類的索引
l 檢索始終返回空結果
l 驗證轉儲文件語法
l 根據二進制日誌記錄度量開銷
l “空操作” 存儲引擎,可用於查找與存儲引擎無關的性能瓶頸
l 識別事務
提交的事務寫入二進制日誌,回滾的事務不寫入