MySQL鎖mysql
在mysql併發訪問時,若是多個用戶在訪問同一張表時,例如用戶A在執行修改表的操做,而同時用戶B發起對該表查詢操做,此時須要讓用戶B知道用戶A正在施加寫操做,這就意味着用戶B此刻須要等待,如何等待,那就須要用到MVCC(併發訪問控制)機制,而該機制是基於鎖來完成;對於多個用戶同時讀來說是沒有問題的,可是同時寫,勢必會致使系統崩潰;因此鎖並不是是無關緊要的,而是必須具有的,尤爲是在併發訪問的模型下.sql
執行操做時施加的鎖模式數據庫
讀鎖:共享鎖、非阻塞阻塞、防止咱們在讀取、查詢所的時候,別人去執行寫操做;緩存
寫鎖:獨佔鎖,排它鎖;彼此間是阻塞安全
鎖粒度:服務器
表鎖:TABLE LOCK 鎖定了整張表架構
行鎖:ROW LOCK 鎖定了須要的行併發
粒度越小,開銷越大,但併發性越好;ide
粒度越大,開銷越小,但併發性越差;函數
鎖的實現位置:
mysql鎖:能夠手動請求顯示鎖;
存儲引擎鎖:自動進行的(隱式鎖);
顯示鎖(表級)
LOCK TABLES
UNLOCK TABLES
語法:
LOCK TABLES tbl_name [[AS] alias] lock_type[, tbl_name [[AS] alias] lock_type] ... |
lock_type:鎖類型: READ [LOCAL] | [LOW_PRIORITY] WRITE |
例子1(施加讀鎖) |
mysql> LOCK TABLES classes READ; //我對此表施加爲讀鎖: mysql> UNLOCK TABLES; //解鎖 |
例子2(施加寫鎖) |
mysql> LOCK TABLES classes WRITE; //我對此表施加爲讀鎖(若是別人也施加了寫鎖,那我這裏會失敗的) mysql> UNLOCK TABLES; //解鎖 mysql> INSERT INTO classes VALUE (9,'taoyuanji',34); //當寫鎖被解鎖後當即完成查詢操做(看它的時間) |
InnoDB存儲引擎也支持另一種顯示鎖(鎖定挑選出的部分行,行級鎖);
SELECT ......LOCK IN SHARE MODE; SELECT ......FOR UPDATE; |
事務:Transaction
事務就是一組原子性的查詢語句,將多個查詢看成一個獨立單元.
ACID測試:能知足ACID測試就表示其支持事務,或兼容事務.
A:Atomicity 原子性 C:Consistency 一致性 I:Isolation 隔離性,一個事務的全部修改操做在提交以前對其餘事務是不可見的 D:Durability 持久性,一旦事務獲得提交,其所作的修改會永久有效 |
隔離級別:
READ UNCOMMITTED(讀未提交) 髒讀,不可重讀;可以看到別人還沒有提交的修改 READ COMMITTED(讀提交) 不可重讀,幻讀 REPEATABLE READ(可重讀) 幻讀 SERIALIZABLE(可串行化) 強制事務的串行執行避免了幻讀 |
事務回滾
mysql>HELP CONTENTS; mysql>HELP Transcations mysql>START TRANSACTION 開啓事務 mysql>COMMIT 提交 mysql>ROLLBACK 回滾 |
設置回滾點
mysql>SAVEPOINT identifier |
回滾到指定的位置
mysql>ROLLBACK [WORK] TO [SAVEPOINT] identifier RELEASE SAVEPOINT identifier |
若是沒有顯示啓動事務,每一個語句都會看成一個單獨的事務,其執行完成後會被自動提交;
查看自動提交是否啓用
mysql>SHOW GLOBAL VARIABLES LIKE 'autocommit'; or mysql>SELECT @@ GLOBAL.autocommit; |
設置自動提交爲關閉,一旦關閉咱們就須要手動就行提交
mysql>SET GLOBAL autocommit = 0; |
查看Mysql的事務隔離級別
mysql>SHOW {GLOBAL|SESSION} VARIABLES LIKE 'tx_isolation'; or mysql>SELECT @@{GLOBAL|SESSION}.tx_isolation; |
設置隔離級別:
mysql>set {GLOBAL|SESSION} tx_isolation '各隔離級別名' |
建議:
對事物要求不特別嚴格的場景下,可使用讀提交
MVCC :多版本併發控制
每一個事務啓動時,InnoDB會爲每一個啓動的事務提供一個當下時刻的快照;
爲了實現此功能,INNODB會爲每一個表提供兩個隱藏的字段,一個用於保存行的建立時間,一個用於保存行的失效時間
Mysql存儲引擎:
MySQL存儲引擎:存儲引擎也一般稱做"表類型"
查看本mysql服務器所支持的存儲引擎:
mysql>SHOW ENGINES; |
查看錶的存儲引擎
mysql>SHOW TABLE STATUS [{FROM | IN} db_name] [LIKE 'pattern' | WHERE expr] |
一張表中的狀態詳細信息
Name: 表名 {DEFAULT|DUNAMIC|FIXED|COMPRESSED|PREDUNDANT|COMPACT} Rows: 表中的行數 Avg_row_length: 平均每行包含的字節數 Max_data_length: 表的最大佔用空間的容量 |
各存儲引擎的特性:
InnoDB:
事務:事務日誌 外鍵: MVCC:多版本併發控制 聚簇索引: 聚簇索引(對於INNODB來講)以外的其餘索引,一般成爲輔助索引 輔助索引-->聚簇索引-->數據 索引類型:B樹索引, R樹索引, hash索引, 全文索引 行級鎖:間隙鎖 支持輔助索引: 支持自適應hash索引 支持熱備份 |
MyISAM:
全文索引: 支持表壓縮,用因而實現數據倉庫,能節約存儲空間並提高性能 空間索引 表級鎖 延遲更新索引 不支持事務, 外鍵, MVCC, 行級鎖;崩潰後沒法安全恢復數據; 適用場景:只讀數據, 較小的表, 多讀少寫 |
ARCHIVE:
僅支持INSERT和SELECT,支持很好的壓縮功能 適用於存儲日誌信息,或其餘按照時間序列實現的數據採集類的應用; 不支持事務,不能很好的支持索引; |
CSV:
將數據存儲爲CSV格式,不支持索引;僅適用於數據交換場景; |
BLACKHOLE:
沒有存儲機制,任何發往此引擎的數據都會被丟棄;其會記錄二進制日誌,所以,經常使用於多級複製架構中做中轉服務器; |
MEMORY:
保存數據在內存中,內存表;經常使用於保存中間數據,如週期性的聚合數據等;也用於實現臨時表 支持hash索引,使用表級鎖,不支持BLOB和TEXT數據類型; |
MRG_MYISAM:
是MYISAM的一個變種,可以將多個MyISAM表合併一個虛表; |
NDB:
是MySQL CLUSTER中專用的存儲引擎 |
第三方存儲引擎:
OLTP類:
XtraDB:加強的InnoDB,由Percona提供; 編譯安裝mysql時下載XtraDB的源碼替換存儲引擎中的InnoDB的源碼 PBXT:MariaDB自帶此存儲引擎 支持引擎級別的複製、外鍵約束、對SSD磁盤提供適當的支持; 支持事務、MVCC ToKuDB:使用Fractal Trees索引,適用於存儲大數據,擁有很高的壓縮比;已經被引入MariaDB; |
列式存儲引擎:
Infobright:適用於海量數據存儲場景,如PB級別,專爲數據分析和數據倉庫設計; InfiniDB MonetDB LucidDB |
開源社區存儲引擎
Aria:前身Maria,加強版的MyISAM(支持崩潰後安全恢復,支持數據緩存) Groona:全文索引引擎;完成全站搜索——>改進版,基於Mroonga二次開發 OQGraph:由Open Query研發,支持圖結構的存儲引擎 SphinxSE:爲Sphinx全文搜索服務器提供了SQL接口 Spider:能將數據切分紅不一樣分片,比較高效透明地實現了分片,並支持在分片上支持並行查詢; |
更多詳細信息能夠參考此表
如何選擇一個適合於本身的存儲引擎:
1.是否須要事務 2.備份的類型的支持 3.崩潰後的恢復 4.特有的特性 綜合考慮便可! |
Mysql用戶管理:
用戶帳號:'username'@'hostname',password
用戶帳號管理:
mysql>CREATE USER mysql>DROP USER mysql>RENAME USER mysql>SET PASSWORD |
權限管理:
mysql>GRANT mysql>REVOKE |
建立用戶:默認獲取到的受權爲USAGE
mysql>CREATE USER 'username'@'hostname' [IDENTIFIED BY [PASSWORD] 'password' ]; |
查看用戶可以使用的權限:
mysql>SHOW GRANTS FOR 'username'@'hostname' |
用戶名更名:
mysql>RENAME old_'username'@'hostname' TO new_'username'@'hostname' |
設置密碼:
mysql>SET PASSWORD FOR 'username'@'hostname' |
Mysql用戶權限管理:
MySQL的權限類別:
管理類權限:
CREATE TEMPORARY TABLES 建立臨時表 CREATE USER 建立用戶 FILE 在服務器上讀取或寫入文件 SUPER 不便歸類的權限,雜項 SHOW DATABASES 列出數據庫 RELOAD 重置 SHUTDOWN 關閉服務器 REPLICATION SLAVE 複製從服務器的權限,從服務器到主服務器上覆制數據須要SLAVE權限從服務器上的用戶必須具備上面兩個權限才能從主服務器上覆制數據 REPLICATION CLIENT 複製客戶端權限,若是一個用戶須要到服務器上獲取複製主機的相關信息,須要CLIENT權限 LOCK TABLES 顯示施加表鎖 PROCESS 查看線程列表(msyql>SHOW PROCESSLIST) |
庫級別和表級別:
ALTER 修改TABLE ALTER ROUTINE 修改存儲歷程(存儲過程、存儲函數) CREATE 建立表和庫 CREATE ROUTINE 建立存儲過程或存儲函數 CREATE VIEW 建立視圖 DROP 刪除庫或表 EXECUTE 執行存儲過程或存儲函數 GRNAT OPTION 把本身得到的權限轉讓 INDEX 建立和刪除索引 SHOW VIEW 查看一個視圖是如何建立的 |
數據操做(表級別):
SELECT 刪除 INSERT 插入 UPDATE 更新 DELETE 刪除 |
字段級別:
SELECT(col1,...) UPDATE(col1,...) INSERT(col1,...) |
全部權限:
ALL [PRIVILEGES] |
GRANT命令用法
GRANT ALL ON [FUNCTION] *.* GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ... ON [TABLE|FUNCTION|PROCEDURE] priv_level TO username@hostname [IDENTIFIED BY 'password'], [username@hostname [],...] [REQUIRE SSL] [WITH with_option ...] priv_level: * 全部對象 | *.* 全部庫的全部對象 | db_name.* 指定庫的全部對象 | db_name.tbl_name 指定庫的制定表 | tbl_name 指定表 | db_name.routine_name 指定庫的存儲歷程 with_option: GRANT OPTION 把本身得到的權限轉贈給其餘用戶 | MAX_QUERIES_PER_HOUR count 每小時所執行的最多查詢請求次數 | MAX_UPDATES_PER_HOUR count 每小時所執行的最多更新次數 | MAX_CONNECTIONS_PER_HOUR count 每小時所能創建鏈接的次數 | MAX_USER_CONNECTIONS count 指定某個用戶賬號最多能同時使用一個賬號鏈接的次數 |
收回受權:
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON [object_type] priv_level FROM user [, user] ... REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ... |
跟用戶受權相關的表:
db:庫級別權限 host:主機級別權限,已廢棄 tables_priv:列級別的權限 procs_priv:存儲過程和存儲函數相關的權限 proxies_priv:代理用戶權限 |
MySQL查詢緩存:
MySQL查詢緩存的功能主要是將查詢計劃執行結果緩存下來,當多個用戶執行相同操做時會加快查詢操做;
兩種緩存機制:
1.查詢語句提交給存儲引擎執行以前,這個查詢計劃必定是作了解析的,若是能將這個查詢計劃緩存下來,當同一個用戶請求相應操做時就不用去解析了;
2.將查詢後返回的數據給緩存下來,它可以保存查詢返回的完整結果;被命中時,MySQL會當即返回結果,省去解析、優化和執行等階段。
緩存機制大體流程
當一個查詢請求進入服務器檢查是否被命中,若是命中則直接返回;若是不然須要解析語句、優化、執行,執行後的結果最後檢查可否須要緩存,若是須要緩存則就將就結果存入緩存當中;因此這樣一來只要咱們開啓了緩存功能它都會去檢查緩存,這樣一來就多了一些開銷、步驟;
如何檢查緩存?
MySQL保存結果於緩存中:
把SELECT語句自己作hash計算,計算的結果做爲key,查詢結果做爲value
什麼樣的語句不會被緩存?
查詢語句中有一些不肯定數據時,不會緩存:例如NOW(), CURRENT_TIME();通常來講,若是查詢中包含用戶自定義函數、存儲函數、用戶變量、臨時表、mysql庫中系統表、或者任何包含權限的表,通常都不會緩存;
緩存會帶來額外開銷:
一、每一個查詢都得先檢查是否命中;
二、查詢結果要先緩存;
查詢緩存徹底是在內存中實現的,而內存空間是有限的,可以分配給查詢緩存使用的空間也是有限的,若是空間佔滿了,那麼會經過緩存策略將那些老的緩存給清除,可是這個過程又會增長開銷,反覆存入、釋放、存入、釋放,內存中就會產生許多碎片,就會變得很麻煩,因而選擇一個合適的緩存策略是一個值得思考問題.
在mysql服務器上設定緩存策略:
查看當前mysql服務器的緩存變量
mysql> SHOW GLOBAL VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name | Value |
+------------------------------+----------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 16777216 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+----------+
query_cache_type: 查詢緩存類型;是否開啓緩存功能,開啓方式有三種{ON|OFF|DEMAND};
DEMAND:按需緩存;意味着SELECT語句明確使用 SQL_CACHE 選項時纔會緩存;
query_cache_size: 總空間,單位爲字節,大小必須是1024的整數倍。MySQL啓動時,會一次分配並當即初始化這裏指定大小的內存空間;這意味着,若是修改此大小,會清空緩存並從新初始化的.
query_cache_min_res_unit: 存儲緩存的最小內存塊;(query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache可以得到一個理想的值.
query_cache_limit: 單個緩存對象的最大值,超出時則不預緩存;手動使用SQL_NO_CACHE能夠人爲地避免嘗試緩存返回結果超出此參數限定值的語句.
query_cache_wlock_invalidate: 若是某個表被其它用戶鏈接鎖住了,是否仍然從緩存中返回結果。OFF表示返回.
如何判斷命令率:
查看當前mysql服務器的緩存狀態變量(不可設定,只需觀測)
mysql> SHOW GLOBAL STATUS LIKE 'Qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 16751304 |
| Qcache_hits | 1 |
| Qcache_inserts | 8 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 33 |
| Qcache_queries_in_cache | 5 |
| Qcache_total_blocks | 14 |
+-------------------------+----------+
Qcache_free_blocks 空閒的塊數
Qcache_free_memory 尚且空閒緩存空間大小
Qcache_hits: 緩存命中次數
Qcache_inserts: 向緩存空間中緩存數據的次數
Qcache_lowmem_prunes 因內存太少,修減內存的次數
Qcache_not_cached 沒有緩存的
Qcache_queries_in_cache在緩存中緩存的查詢的個數
Qcache_total_blocks 總塊數
緩存空間只有被初始化、分配之後用來緩存數據的;
空閒空間表示還沒有劃分用來存數據格式的空間
總空間 - 剩餘空間 = 已用空間
並不是已用空間都存了緩存,裏面有的表示已劃分好格式了,隨時等待緩存,但還沒有進行緩存
若是內存中確實有碎片了,而內存還有足夠的空間;這是咱們須要進行碎片整理
碎片整理:FLUSH QUERY_CACHE
清空緩存:RESET QUERY_CACHE
計算命中率:
1.經過如下語句獲取查詢次數和命中次數這兩個值
mysql> SHOW GLOBAL STATUS WHERE Variable_name='Qcache_hits' OR Variable_name='Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 57 |
| Qcache_hits | 8 |
+---------------+-------+
2.經過下面這個公式計算
Qcache_hits/(Com_select +Qcache_hits)
也應該參考另一個指標:命中和寫入的比率,即Qcache_hits/Qcache_inserts的值,此比值若是能大於3:1,則代表緩存也是有效的。能達到10:1,爲比較理想的狀況。
緩存優化使用思路:
一、批量寫入而非屢次單個寫入;
二、緩存空間不宜過大,由於大量緩存同時失效時會致使服務器假死;
三、必要時,使用SQL_CACHE和SQL_N0_CACHE手動控制緩存;
四、對寫密集型的應用場景來講,禁用緩存反而能提升性能;
MySQL日誌:
查詢日誌:用來保存當前系統上全部跟查詢相關信息的(不只僅只包含SELECT)
慢查詢日誌:查詢執行時長超過指定時長的查詢;未必是執行語句自身緣由,多是應爲被依賴的資源不被許可訪問.定位系統上查詢操做、執行過慢時的一個評估工具,因此有必要啓用之.
錯誤日誌:MySQL啓動時,複製
二進制日誌:記錄了mysql數據庫中引發數據庫改變的全部操做或有潛在跟修改相關的操做,若是要從頭記錄的話拿到其餘服務器上還原後與原服務器基本相同;mysql的複製功能依賴於此日誌複製功能.
中繼日誌:slave server從master server的二進制文件中複製事件過來,並保存至本地的日誌文件中,此日誌文件就叫作中繼日誌
事務日誌:暫存事務提交的數據
將隨機I/O轉換爲順序I/O,保證事務的ACID
日誌文件組:至少應該有兩個/保證事務回滾、提交、一致性
查詢日誌:(默認是關閉的)
log={ON|OFF}:是否記錄全部語句的日誌信息於通常查詢日誌文件中(general_log)
log_output={TABLE|FILE|NONE} TABLE|FILE 能夠同時出現,用逗號分隔
general_log={ON|OFF}
general_log_file:定義通常查詢日誌保存位置
SET GLOBAL log='ON'
SET GLOBAL general_log='ON' --->數據目錄下:hostname.log
都須要啓用
若是記錄到TABLE中 SET GLOBAL log_output='TABLE'
會記錄到數據庫的mysql數據庫general_log表中
慢查詢日誌:
慢查詢時長:超過此時間,就斷定爲慢查詢;
mysql> show global variables like 'long%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)
設定是否啓用慢查詢日誌:
是否啓用慢查詢日誌,它的輸出位置也取決於log_output={TABLE|FILE|NONE}
slow_query_log={ON|OFF}
定義日誌文件路徑及名稱:
slow_query_log_flile=www-slow.log
#過濾器
log_slow_filter=admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk
#是否啓用記錄慢查日誌
log_slow_queries=ON
#定義慢查速率
log_slow_rate_limit=1
#是否記錄詳細格式的日誌信息
log_slow_verbosity
錯誤日誌:
服務器啓動和關閉過程當中的信息;
服務器運行過程當中的錯誤信息;
時間調度器運行一個事件時產生的信息;
在複製架構中的從服務器上啓動從服務器線程時產生的信息;
相關參數:
log_error /data/mydata/www.stu41.com.err -->錯誤日誌路徑及名稱
log_warnings 1 -->默認記錄了mysql服務器的警告信息
二進制日誌:
時間點恢復
實現mysql的複製