1. 程式人生 > >【資料庫】MySQL記錄概要

【資料庫】MySQL記錄概要

MySQL記錄概要

時間函式

  • curdate() : yyyy-MM-dd
  • curtime() : HH:mm:ss
  • now() : yyyy-MM-dd HH:mm:ss
  • from_unixtime() : 返回時間戳的日期值
  • unix_timestamp(date) : 時間戳
  • date_format(date,fmt) : fmt格式化日期
    • fmt: %Y-%m-%d %H:%i:%s
  • date_add(date,interval expr type):當前日期加上一定時間間隔
    • expr type: HOUR(hh)、MINUTE(mm)、SECOND(ss)、YEAR(YY)、MONTH(MM)、DAY(DD)、YEAR_MONTH(YY-MM)、DAY_HOUR(DD hh)、DAY_MINUTE(DD hh:mm)、DAY_SECOND(DD hh:mm:ss)、HOUR_MINUTE(hh:mm)、HOUR_SECOND(hh:ss)、MINUTE_SECOND(mm:ss)
  • datediff(startDate,endDate):返回兩個日期之間的天數
  • 其餘日期
    • week、year、hour、minutes、monthname

流程函式

  • IF(value,true,false)
  • IFNULL(value,replaceValue)
  • CASE [expr] WHEN [value] THEN [result] ELSE [defalut] END

字串函式

  • CANCAT(str1,str2,…strn) 連線字串
  • INSERT(str,x,y,instr) 字串str在(x,y)位置替換instr
  • LOWER(str) 小寫
  • UPPER(str) 大寫
  • LEFT(str,x) 最左邊的x個字元
  • RIGHT(str,x) 最右邊的x個字元
  • LTRIM(str)/RTRIM(str) 去掉左右空格
  • REPLACE(str,a,b) b替換str中出現的a
  • SUBSTRING(str,x,y) 返回(x,y)長度的字串

數值函式

  • ABS(x) 返回x的絕對值
  • CEIL(x) 返回大於x的最大整數值
  • FLOOR(x) 返回小於x的最大整數值
  • MOD(x,y) x/y的模
  • RAND() 0~1內的隨機值
  • ROUND(x,y) 四捨五入
  • TRUNCATE(x,y) 截斷小數位結果

其他函式

  • DATABASE() 資料庫
  • VERSION() 版本
  • USER() 當前使用者
  • PASSWORD() 加密方式
  • MD5() MD5字串
  • INET_ATON(IP) 返回IP的數字表示
  • INET_NTOA(num) 返回數字代表的IP地址

MYSQL工具

  • MySQL Administrator 管理工具
  • MySQLdump 備份工具
  • Catalogs 控制檯提供的管理表、索引、檢視和過程的工具
  • MySQL Query Brower 視覺化介面的mysql管理工具
  • phpMyAdmin 通過web控制操作資料的工具
  • mysqlbinlog 檢視binlog

備份

  • InnoDB Online Backup 保障InnoDB資料一致性
  • Lock all tables 確保MyISAM資料一致性
  • Online with binlog pos 實現InnoDB Backup功能,科記錄Binlog位置,便於恢復
  • Normal backup 只有備份每個表時才鎖定單表,表間一致性無法保障
  • Complete backup 資料庫全備份

MySQL儲存引擎

檢視Mysql支援的儲存引擎

show ENGINE \G  

設定表的儲存引擎

create table table_name() ENGINE=InnoDB CHARSET=utf-8

修改表的儲存引擎

alter table_name ENGINE MyISAM

如何選擇引擎

  • MyISAM:預設的MySQL引擎,對資料一致性要求、完整性和併發性不是很高的插入/查詢操作,很少更新刪除操作
  • InnoDB:支援事務、外來鍵,在併發條件保證資料一致性。對資料準確性較為精確
  • MEMORY:資料儲存在記憶體中,訪問速度快。適用於快速定位記錄。但是對錶大小有限制,確保資料可以恢復,用於更新不太頻繁的小表
  • MERGE:一系列等同的MyISAM表以邏輯方式組合,作為物件引用它們。優點是突破對單個MyISAM表大小限制

索引

建立索引語法

create [UNIQUE|FULLTEXT|SPATIAL] INDEX idx_name
  [USING index_type]
  ON table_name(idx_col_name)

設定索引原則

  1. 搜尋的索引列。最適合索引的列是出現在where子句中的列,或連線子句中指定的列
  2. 使用唯一索引。考慮某列中值分佈,索引列基數越大,索引效果越好
  3. 使用短索引。對字串進行索引,應該指定一個字首長度。
  4. 最左字首。在建立一個n列索引,實際上是建立mysql可利用的n個索引,多列索引可起幾個索引的作用,可利用索引最左邊的列集匹配行
  5. 不要過度索引。每個額外的索引都要佔據額外的磁碟空間,降低寫操作效能。在修改表內容時,索引必須進行更新,花的時間更長。
  6. 對於InnoDB的表,預設會按照一定順序排好,若定義了主鍵,按照主鍵順序儲存,沒有主鍵,但是有唯一索引,按照唯一索引順序儲存。如果既沒有主鍵,有沒有唯一索引,那麼表會自動生成一個內部列,按照這個列的順序儲存。主鍵儘可能選擇較短的資料型別,有效的減少索引的磁碟佔用,提高索引的快取效果

BTree索引和Hash索引

MEMORY儲存引擎時可以使用

HASH重要特徵

  1. 只用於=或<=>操作符之間的比較
  2. 優化器不能使用hash索引加速orderby
  3. mysql不能確定在兩個值之間大約有多少行。如果將MyISAM改為HASH索引的MEMORY表,將會影響查詢效率
  4. 只能使用整個關鍵字搜尋一行

BTree特徵

  1. 對於<、>、!=、<>、between或者like ‘pattern’時。都可以使用

適用於Hash和BTree索引

select * from table_name where key_col = 1 or key_col in (1,2,3);

只適用於btree索引

select * from table_name where key_col > 1 and key_col < 10;
select * from table_name where key_col like 'ab%' or key_col between 'a' and 'b';

HASH索引實際是全表掃描的

分散式事務

語法

啟動XA事務

XA {START|BEGIN} xid [JOIN|RESUME]

XA START xid 用於啟動一個帶給定xid值的XA事務。每個XA事務必須有一個唯一的xid值

xid是一個XA事務識別符號,用來標識一個分散式事務。xid值由客戶端提供,MySQL伺服器生成

xid包含三個部分

xid: gtrid [, bqual [, formatID ]]
  • gtrid:分散式事務識別符號,相同的分散式事務應該使用相同的gtrid,可以明確xa事務屬於哪個分散式
  • bqual:分支限定符,預設值為空串。對於一個分散式事務中的每個分支事務必須是唯一的
  • formatID:數字。用於標識由gtrid和bqual值使用的格式,預設為1

進入PREPARE狀態(兩階段提交的第一階段)

XA END xid [SUSPEND [FOR MIGRATE]]

XA PREPARE xid

提交/回滾具體的分支事務 (兩階段提交的第二階段)

XA COMIT xid [ONE PHASE]

XA ROLLBACK xid

返回當前資料庫處於PREPARE狀態的分支事務的詳細資訊

XA RECOVER

分散式關鍵在於如何確保分散式事務的完整性,以及在某個分支出現問題時的故障解決。

XA的相關命令就是提供給應用如何在多個獨立的資料庫之間進行分散式事務的管理,包括啟動一個分支事務、使事務進入準備階段以及事務的實際提交回滾操作等

舉例:在DB1中插入一條記錄,同時在DB2更新一條記錄,兩個操作作為同一事務提交或回滾

  1. 在資料庫DB1中啟動一個分散式事務和分支事務,xid的gtrid為”test”,bqual為”db1”

    mysql> xa start 'test','db1';
    mysql> insert into t_products values(5,2,'測試商品',50,'分散式測試');
    mysql> xa end 'test','db1';
    mysql> xa prepare 'test','db1';
    
    mysql> xa recover;
    *************************** 1. row ***************************
    formatID: 1
    gtrid_length: 4
    bqual_length: 3
    data: testdb1
    
  2. 在資料庫DB2中啟動一個分散式事務和分支事務,xid的gtrid為”test”,bqual為”db2”

    mysql> xa start 'test','db2';
    mysql> insert into producttype values(MD5('77'),now(),now(),'分散式測試');
    mysql> xa end 'test','db2';
    mysql> xa prepare 'test','db2';
    
    mysql> xa recover;
    *************************** 1. row ***************************
    formatID: 1
    gtrid_length: 4
    bqual_length: 3
    data: testdb2
    
  3. 提交分支事務

    mysql> xa commit 'test','db1';
    mysql> xa commit 'test','db2';
    

注意:兩個事務都達到準備提交階段後,一旦開始進行提交操作,需要確保全部分支提交成功

存在的問題

1.如果分支事務達到prepare狀態,資料庫異常重新啟動,伺服器重新啟動後,可以繼續對分支事務進行提交或者回滾操作,但是提交的事務沒有寫binlog,存在一定隱患。可能導致binlog恢復丟失部分資料。

2.如果存在複製的資料庫,則有可能導致主從資料不一致。因為複製和災難恢復都依賴於binlog

SQL安全

SQL注入

SQL注入攻擊者可以利用它讀取,修改或者刪除資料庫內的資料。一般的防火牆無法進行Sql注入攔截

“/*”或者”#”可以將後面的語句註釋掉

應對措施

PrepareStatement + Bind-variable

對於JSP、Java開發的應用來防止SQL注入

String sql = "select userName from userName = ? and userPassword = ?";
PrepareStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,pwd);
ResultSet rs = pstmt.executeQuery();

SQL Mode

SQL Mode定義MySql應該支援的SQL語法、資料校驗等

SQL Mode 常用來解決

  • 通過設定SQL Mode,可以完成不同嚴格程度的資料校驗,保障資料準確性
  • 通過設定SQL Mode為ANSI模式,保證大多數SQL符合標準SQL語法(確保進行不同資料庫遷移時,不需要對業務SQL進行較大的修改)
  • 不同資料庫遷移之前,通過SQL Mode可以使MySQL上的資料更方便遷移到目標資料庫中

    mysql> select @@sql_mode;
    
    +----------------------------------------------------------------+
    | @@sql_mode                                                     |
    +----------------------------------------------------------------+
    | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
    +----------------------------------------------------------------+
    
  • set [session/global] sql_mode = ‘STRICT_TRANS_TABLES’ : 設定嚴格模式。當記錄插入失敗,直接失敗。返回ERROR

RAND提取隨機行

 -- 按照資料隨機排序,並選擇前10
 select * from table_name order by rand() limit 10;

按照隨機順序檢索資料行

GROUP BY 的 WITH ROLLUP 做統計

可以檢索出更多的分組聚合資訊。with rollup反映的是一種OLAP思想

注意:
1.當使用ROLLUP時,不能同時使用ORDER BY
2.LIMIT用在WITH ROLLUP的後面

SQL 優化

通過show status瞭解各種SQL執行頻率

  show status like 'Com_%';
  • Com_select: 查詢操作次數
  • Com_insert: 新增操作次數
  • Com_delete: 刪除操作次數
  • Com_update: 修改操作次數

檢視事務提交回滾情況
- Com_commit
- Com_rollback

   show status like 'Innodb_%';
  • Innodb_rows_read: select返回的行數
  • Innodb_rows_inserted: 執行insert插入的行數
  • Innodb_rows_updated: 執行update更新行數
  • Innodb_rows_deleted: 執行delete刪除行數

對於回滾操作非常頻繁的資料庫,可能以為編寫存在問題

  • Connections 試圖連線MySql伺服器的次數
  • Uptime:伺服器工作時間
  • Slow_queries: 慢查詢次數

定位執行效率較低的SQL語句

  • 通過慢查詢日誌定位
    • 用log-slow-queries[=file_name]啟動時,mysqlId寫一個包含所有執行時間超過long_query_time秒的SQL語句的日誌檔案
    • 慢查詢日誌在查詢結束後記錄,只能反應效率不能定位問題
  • 使用show processlist檢視MySQL進行中的執行緒(包括執行緒狀態、是否鎖表等)、實時檢視SQL執行情況

通過EXPLAIN/DESC分析低效SQL執行計劃

  • select_type
    • SIMPLE:單表
    • PRIMARY:外層查詢(主查詢)
    • UNION:union中第二個或者後面的查詢語句
    • SUBQUERY:子查詢中的第一個select
  • table: 輸出結果集的表
  • type:表的連線型別
    • 效能由好到差:system>const>eq_ref>ref_or_null>index_subquery>unique_subquery>index_subquery>range>index>all
    • 表中僅有一行(常量表)>單表中最多一個匹配行pk和uq_idx>多表連線中使用pk和uq_idx>使用普通索引>與ref類似包含對NULL的查詢>索引合併優化>一個查詢主鍵欄位的子查詢>非唯一索引欄位的子查詢>單表中範圍查詢>對於前面的每一行通過查詢索引得到的資料>全表查詢
  • possible_key:可能使用的索引
  • key:實際使用的索引
  • key_len:索引欄位的長度
  • rows:掃描行數量
  • extra:執行情況的說明和描述

        id: 1
        select_type: SIMPLE
        table: region
        partitions: NULL
        type: ALL
        possible_keys: NULL
        key: NULL
        key_len: NULL
        ref: NULL
        rows: 3524
        filtered: 100.00
        Extra: NULL
    

索引儲存分類

MySQL支援的儲存型別

  1. Hash(MEMORY和HEAP兩者都可以使用)
  2. BTree(MyISAM和InnoDB)
  3. 不支援函式索引(根據文字字元長度進行索引)

使用索引

索引用於快速找出在某個列中有一特定值的行。
**使用索引的主要條件是查詢條件中需要使用索引關鍵字,如果是多列索引,需要滿足最左字首原則,才可使用,否則不能使用索引

索引有效/失效

  1. 假設有一個複合索引idx_test(col_1,col_2)。where條件只跟col_1都能匹配到索引,如果where後面只跟col_2則不能匹配
  2. 對於like查詢,%如果在第一個字元,索引則失效
  3. 對於大文字搜尋,使用全文索引,而不是使用like ‘%..%’
  4. 如果列名是索引,使用col_name is null條件,索引有效
  5. 索引比全表掃描滿,則不使用索引。
  6. 如果使用MEMORY/HEAP表並且where條件不適用=進行索引列,則不會使用
  7. 用or分隔開的條件,如果or前的條件中列有索引,而後面沒有索引,則涉及的索引失效
  8. 列型別為字串,在where條件中的字元常量值通過引號。否則索引失效

檢視索引使用情況

mysql> show status like 'Handler_read%'
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 0     | 
| Handler_read_last     | 0     |
| Handler_read_next     | 0     |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+
  • Handler_read_key : 代表行被索引值讀次數。值越高說明索引使用頻率越多
  • Handler_read_rnd_next: 資料檔案讀取下一行請求數。值越高查詢越低下,應該建立索引補救(通常代表索引不正確或沒有利用索引)

優化

  1. 定期分析表和檢查表

    ANALYZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE table_name [,table_name_2,...]
    
  2. 定期優化表

    OPTIMizE [LOCAL|NO_WRITE_TO_BINLOG] TABLE table_name [,table_name_2,...]
    

注意:ANALYZE、CHECK、OPTIMIZE執行期間會對錶進行鎖定

常用SQL優化

1.大批量匯入資料

  • 當用load命令匯入資料時,適當設定提高匯入速度

  • 對於MyISAM引擎表,設定如下

     alter table table_name DISABLE KEYS;
     loading the data
     alter table table_name ENABLE KEYS;
    
  • DISABLE/ENABLE:開啟/關閉MyISAM非唯一索引的更新

     load data infile 'path' into table table_name;
    
  • 對於InnoDB引擎表,設定如下

     set unique_checks = 0 --匯入資料前,關閉唯一性校驗
     set unique_checks = 1 --匯入結束後,恢復唯一性校驗
    
  • 如果使用自動提交方式

     set autocommit = 0 --關閉自動提交
     set autocommit = 1 --開啟自動提交
    

2.優化insert

  • 同一使用者插入很多行,儘量使用多個值表的insert語句。縮減客戶端與資料庫之間的連線/關閉消耗

    insert into table_name values(),(),()...
    
  • 不同使用者插入很多行,使用insert delayed得到更高的速度

    • delayed讓insert語句馬上執行,其實是放在記憶體都列中,並沒有寫入磁碟。比每條語句插入快。LOW_PRIORITY相反,在所有其他使用者對錶的讀寫完後才進行插入
  • 索引檔案和資料檔案分別放在不同的磁碟
  • 如果進行批量插入,增加bulk_insert_buffer_size提高速度,只對MyISAM使用
  • 當從一個文字檔案載入一個表時,使用load data infile。比insert快

3.優化GROUP BY

  • order by null : 禁止排序。避免排序結果消耗

4.優化ORDER BY

  • 在某些情況,使用一個索引滿足order by而不需要額外排序。where和order by使用的是相同索引。
  • 混用DESC、ASC索引不生效
  • 查詢行的關鍵字與ORDER BY中不一致

5.優化巢狀查詢(子查詢)

  • 通過子查詢建立一個單列的查詢結果,然後把這個結果作為過濾條件在另外一個條件中。使用子查詢避免事務或者表鎖死。某些情況下子查詢被更有效率的JOIN替代

6.優化OR條件

  • OR之間的每個條件列都必須用到索引

    show index from table_name --檢視某表上索引 
    

7.使用SQL提示

  • SQL中加入一些人為提示達到優化操作的目的

8.use index

  • 查詢語句表名後面,新增use index提供希望mysql參考的索引列表

    select * from table_name use index (idx_test_id) where ...
    

9,ignore index

  • 忽略一個或者多個索引

10.force index

  • 強制使用一個特定索引

11.字串索引

  1. 只是用字串的最左邊n個字元建立索引,推薦n<=10;比如index left(column,8),但是需要知道字首索引不能在order by中使用,也不能用在索引覆蓋上。
  2. 對字串使用hash方法將字串轉化為整數,column_key=hashToInt(column),對column_key建立索引

優化資料庫物件

1.優化表的資料型別

  • PROCEDURE ANALYSE() 對當前表進行分析

     select * from table_name PROCEDURE ANALYSE()
    

2.通過拆分提高表的訪問效率

  • 垂直拆分:eg.OrderMain和OrderDetail
    • 優點:資料行變小,資料頁存放更多資料,查詢時減少I/O次數
    • 缺點:管理冗餘列。查詢時需要JOIN操作
  • 水平拆分:將一列或多列資料值放到兩個獨立表中
    • 表很大,分割後降低在查詢時需要讀的資料和索引頁數。降低索引層數
    • 資料獨立性
    • 資料存放在多個介質中
    • 缺點:增加複雜度

3.逆規範化

適當考慮表的冗餘欄位,不需要在做關聯查詢,而讓查詢有更好的效能。
逆規範的好處是降低連線操作的需求和索引數目。甚至可能減少表數目。但是可能影響資料完整性。

  • 增加冗餘列
  • 增加派生列
  • 重新組表
  • 分割表

4.使用中間表提高統計查詢速度

鎖問題

MySQL在不同儲存引擎下支援不同的鎖機制

  • 表級鎖:MyISAM和MEMORY
  • 頁面鎖:BOBO
  • 行級鎖:InnoDB(也支援表級鎖)

3種鎖的特性

  • 表級鎖:開銷小,加鎖快。不會出現死鎖;鎖定粒度大,發生鎖衝突頻率最高,併發度最低
  • 行級鎖:開銷大,加鎖慢,會出現死鎖;鎖定粒度小;發生鎖衝突概率最低,併發度最高
  • 頁面鎖:開銷介於表鎖和行鎖之間,會出現死鎖。鎖定粒度介於表鎖行鎖之間。併發程度一般

MyISAM表鎖

查詢表爭用情況

   show status like 'table%';
  • Table_locks_waited:值越高,則說明存在嚴重的表級鎖爭用
    • MyISAM讀鎖不會其他使用者對同一個表的請求,但會阻塞同一個表的寫請求。一個執行緒獲得表的寫鎖後。只有持有鎖的執行緒對錶進行更新操作。其他的讀執行緒等待。直到被釋放。

顯式加鎖

Lock tables table_name_1 read local, table_name_2 read local
... --sql語句
Unlock tables

獲取鎖

 lock table table_name as alias read;

併發插入

MyISAM的讀寫序列,在一定條件下,MyISAM表也支援查詢和插入操作的併發進行

 concurrent_insert --控制其併發插入的行為
  • concurrent_insert=0 不允許併發插入
  • concurrent_insert=1 MyISAM允許在一個程序讀表的同時,另一個程序從表尾插入記錄(預設設定)
  • concurrent_insert=2 都允許在表尾併發插入記錄

MyISAM鎖排程

寫程序獲取鎖,讀請求先到鎖等待佇列,寫請求厚道,寫鎖會插入到讀鎖請求之前。(由於一特性,myISAM不適合大量更新和查詢操作。大量更新操作會造成查詢操作很難獲得鎖,從而一直阻塞。)

  • 指定啟動引數low-priority-updates:預設給予都請求優先
  • set low_priority_updates = 1 使該連線發出的更新請求優先順序降低
  • 指定insert、update、delete的low_priority屬性,降低該語句優先順序

InnoDB行鎖

MyISAM與InnoDB最大不同:支援事務、採用行級鎖。

事務ACID屬性

  • 原子性 (要麼全部執行,要麼全部失敗)
  • 一致性 (事務開始和完成,資料必須保持一致狀態,保持資料完整性)
  • 隔離性 (保證事務不受外部併發操作影響)
  • 永續性:事務一旦提交。對於資料修改是永久的)

併發事務處理帶來的問題

  • 更新丟失:2個或多個事務更新同一行,但是每個事務都不知道彼此的存在,會發生丟失更新問題
  • 髒讀:一個事務正在對一條記錄進行修改,但是並未提交。資料處於不一致狀態;另一個事務讀取同一條記錄,如果不加控制。就會讀取到髒資料,產生未提交資料依賴關係
  • 不可重複讀:一個事務在讀取資料後某個時間按,再次讀取以前讀果的資料,發生了改變(或者已經刪除)
  • 幻讀:一個事務按相同的查詢條件重新讀取以前檢索過的額資料,發現其他事務插入了滿足其查詢條件的新資料

事務隔離級別

  • 讀取資料前,對其加鎖,阻止其他事務對其資料進行修改
  • 不加任何鎖,通過一定機制生成一個數據請求時間點一致性資料快照,並用這個快照提供一定級別的一致性讀取(這種叫做資料庫多版本併發控制,稱為MVCC)

事務隔離越嚴格,併發副作用越小,旦代價越大;事務隔離實質就是使事務在一定程度上”序列化”進行

  • 未提交讀
  • 已提交讀
  • 可重複讀
  • 可序列化

獲取InnoDB鎖爭用情況

show status like 'innodb_row_lock%'
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0     |
| Innodb_row_lock_time          | 0     |
| Innodb_row_lock_time_avg      | 0     |
| Innodb_row_lock_time_max      | 0     |
| Innodb_row_lock_waits         | 0     |
+-------------------------------+-------+

如果鎖爭用的情況比較嚴重。還可以設定Innodb Monitors進一步觀察鎖衝突、資料行。具體分析原因

InnoDB行鎖模式以及加鎖方法

  • 共享鎖S:允許一個事務讀取一行,阻止其他事務獲得相同資料集的排它鎖
  • 排它鎖X:允許獲得排它鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和排他寫鎖
  • 意向共享鎖IS:事務打算給資料行加行共享鎖,事務在給一個數據行加共享鎖前必須取得該表的IS鎖
  • 意向排它鎖IX:事務打算給資料行加排它鎖,事務在給定一個數據行加排它鎖前必須取得該表的IX鎖

    – 共享鎖
    select * from table_name where … LOCK IN SHARE MODE
    – 排它鎖
    select * from table_name where … FOR UPDATE

  • LOCK IN SHARE MODE:從資料依存關係確認某行記錄是否存在,並確保沒有人對這個記錄進行update或者insert操作。但如果當前事務需要對該記錄進行更新操作,可能會造成死鎖‘

  • FOR UPDATE : 對於鎖定行需要進行更新的記錄,使用排他鎖

InnoDB行鎖實現方式

  • InnoDB通過給索引上的索引項加鎖實現。只有通過索引條件檢索資料,InnoDB才使用行級鎖,否則,使用表鎖。
  • 當表遊多個索引,不同事務使用不同索引鎖定不同的行
  • 分析鎖衝突,需要檢查sql執行計劃(explain)

間隙鎖(Next-Key)

通過範圍條件而不是相等條件檢索資料,並請求共享排它鎖時,InnoDB會給符合條件的已有資料記錄的索引項加鎖:對於鍵值在條件範圍內但並不存在的記錄,叫做間隙。InnoDB對這個間隙加鎖

select * from table_name from col_1 > 100 for update

使用間隙的目的
1.防止幻讀,滿足相關隔離級別
2.滿足恢復和複製

select @@tx_isolation;

複製本質:在SlaveMysql不斷做基於binlog的複製
恢復機制:在一個事務未提交前,其他併發事務不能插入滿足其鎖定條件的任何記錄(不允許幻讀)。無論在ReadCommited或者RepeatableRead隔離級別下,InnoDB都要使用間隙鎖

優化MySQL

  show variables --伺服器靜態引數值
  show status  --動態執行狀態
  show warnings

相關引數

  • key_buffer_size
  • table_cache
  • innodb_buffer_pool_size
  • innodb_flush_at_trx_commit
  • innodb_additional_mem_pool_size
  • innodb_lock_wait_timeout
  • innodb_support_xa
  • innodb_log_buffer_size
  • innodb_log_file_size

磁碟陣列(RAID)

RAID級別

  • RAID 0:

    • 特性:條帶化。按一定的條帶大小將資料依次分佈到各個盤中,無資料冗餘。
    • 優點:併發讀寫快。無額外磁碟空間開銷
    • 缺點:資料無冗餘保護,可靠性差
  • RAID 1:

    • 特性:磁碟映象,兩個磁碟一組,所有資料同時寫入兩個磁碟。讀取任一磁碟即可
    • 優點:有冗餘保護。只要不出現兩塊磁碟同時損壞。提高併發讀寫效能
    • 缺點:容量一定的情況,磁碟空間佔用大
  • RAID 10

    • 特性:RAID 0 和 RAID 10 結合。先對磁碟做映象,在條帶化
    • 優點:可靠性高。併發讀寫效能優良
    • 缺點:容量一定的情況,磁碟空間佔用大
  • RAID 4

    • 特性:如RAID 0一樣對磁碟組條帶化,不同的時:需要額外增加一個磁碟。寫各Stripe(條帶)的校驗糾錯資料
    • 優點:RAID中一個磁碟損壞可以通過校驗糾錯資料計算,保障容錯資訊;讀取資料快
    • 缺點:每個Stripe寫校驗糾錯塊,效能有影響。所有糾錯資料在同一磁碟,風險大,容易形成效能瓶頸。出現壞盤,效能下降
  • RAID 5

    • 特性:對RAID 4的改進,將每個條帶的校驗糾錯資料分佈寫到各個磁碟,而不是寫入特定磁碟
    • 優點:效能和資料保護能力強於RAID 4
    • 缺點:寫效能不及RAID 0、RAID 1和RAID 10;容錯能力不及RAID 1

如何選擇RAID級別

  • 資料讀寫很頻繁,可靠性較高,最好選擇RAID 10
  • 資料讀頻繁,寫較少,對可靠性有一定要求,可選RAID 5
  • 資料讀寫都很頻繁,可靠性要求不高,可選RAID 0

使用Symbolic Links分佈I/O

禁止作業系統更新檔案的atime屬性

應用優化

1.使用連線池

2.減少對MySQL的訪問

2.1. 避免對同一資料進行重複檢索
2.2. 使用查詢快取

 show variables like '%query_cache%'

2.3. 增加Cache層

3.負載均衡

2.2. 利用MySQL複製分流查詢操作
- MySQL主從複製有效的分流更新操作和查詢操作
- 具體實現:主伺服器承擔更新操作,多臺伺服器承擔查詢操作;主從之間通過複製進行資料同步;多臺從伺服器確保可用性;另一方面可以通過不同索引滿足不同需要
- 缺點:當主資料庫更新頻繁或者網路出現問題時,主從之間的資料存在比較大的延遲更新造成查詢結果和主資料庫上有所差異

2.3. 採用分散式資料庫結構
- 注:如果使用分散式架構資料庫,必須採用InnoDBZ

4.其他優化

- 對於沒有刪除行操作的MyISAM表,插入和查詢可以並行進行,沒有刪除操作的表查詢期間不會阻塞插入操作。對於需要執行刪除操作的表,儘量在空閒時間執行批量刪除,並在刪除操作後進行optimize。避免將來更新阻塞其他操作
- 充分利用預設值
- 表儘量不適用自增長欄位