mysql優化總結

一, 優化思路

 

    1  拿到待優化的服務器,第一步是觀察,可以通過腳本或者阿里雲的統計圖分析。或者使用top命令查詢服務器信息。

    2  如果出現週期性的波動或者故障,一般都是由訪問的高峯或者緩存崩潰引起,解決方法是增加緩存,修改緩存失效策略,使失效的時間分散3-6小時即可,第二是在夜晚訪問量低的時候定時失效設置

    3  解決過後在觀察統計圖,如果仍有不規則的延遲或者卡頓現象 需要set profiling =1 開啓mysql的執行計劃,或者開啓mysql的慢查詢日誌,slow_query_log=on  以mysqldumpslow工具分析。

    4  如果是語句等待的時間長 優化mysql的參數比如線程數等。

    5  如果是mysql執行的時間長,就是sql語句優化問題和表結構問題,如查詢的表關聯多,沒有使用索引或者索引設置不合理,sql語句沒有優化

    6  如果仍然沒有解決,在用sql的基準測試工具sysbench檢查mysql服務器的性能瓶頸,主要有

                吞吐量:mysql執行事務的能力

                併發性:mysql執行sql語句的效率

                執行時間 等

    滿足要求 就再用此流程優化 如果不滿足 就增加服務器的硬件。

 

二, 分步處理    

 

mysql服務器分析:

1 show status;顯示mysql工作狀態

     queries 當前的查詢數量

     threads_connected 進程的連接數

     threads_running 進程的工作數;   

2 文本分析工具awk

     mysqladmin -uroot ext|awk '/Queries/{q=$4}/Threads_connected/{$c=$4}/threads_running/{r=$4}END{printf("%d %d %d\n",q,c,r)}' >>status.txt

      執行一次返回出上面3個參數的狀態,就可以分析系統的狀態

3請求工具  httpd的ab工具 模擬請求 併發數 總次數

     ab -c 50 -n 200000 http://www.baidu.com 50個併發 200000個請求

 

mysql進程狀態分析 (mysql5.0版本之後)

1.set profiling =1;開啓mysql的執行計劃 爲每條mysql語句分析詳細的過程

2.show processlist 執行計劃 這個命令是顯示當前所有連接的工作狀態.

  需要注意的state狀態參數:

    converting HEAP to MyISAM    查詢結果太大時,把結果放在磁盤 (語句寫的不好,取數據太多)

    create tmp table             創建臨時表(如group時儲存中間結果,說明索引建的不好),臨時表在內存中,數據特別大時會寫入磁盤,數據磁盤異常爆滿時考慮這個情況

    形成臨時表的情況:

    group by 的列沒有索引,必產生內部臨時表

    order by 與group by爲不同列時,或多表聯查時order by ,group by 包含的列不是第一張表的列,將會產生臨時表

    Copying to tmp table on disk   把內存臨時表複製到磁盤 (索引不好,表字段選的不好)

    locked                         被其他查詢鎖住 (一般在使用事務時易發生,互聯網應用不常發生)

    logging slow query             記錄慢查詢

3.show profiles;            mysql 5.5 以後加了一個profile設置,可以觀察到具體語句的執行步驟.

4.show profile for query 2; 爲第二個sql執行計劃。

    也可以格式化輸出:set @query_id=2;

    詳細的展示消耗的時間組成部分

5.show full processlist  查看mysql查詢的狀態,一個查詢生命週期中,狀態會變化多次。

     sleep:線程等待客戶端發送新的請求

     query:正在執行查詢或者正在返回結果給客戶端。

     locked:在服務器層表示等待表鎖,存儲引擎層的鎖不會顯示在線程狀態中。

     analyzing and statistics 線程正在收集存儲引擎統計信息,並生成查詢的執行計劃。

     copying to tmp table [on disk] 結果集複製到臨時表中,group by,order,union操作,on disk將內存表寫入磁盤。

     sorting result 線程正在對結果集進行排序。

     sending data 線程可能在多個狀態間傳遞數據,或者生成結果集 或者向客戶端返回數據。

 

三, sysbench 基準測試工具  (sysbench --test=olpt (desc 描述表的結構))

 

1.基準測試的內容:

    cpu性能

    磁盤io性能

    調度程序性能

    內存分配及傳輸速度

    POSIX線程性能

    數據庫性能(OLTP基準測試)

 

2基準測試的指標:

    吞吐量:單位時間內的事務處理數。

    相應時間或者延遲:百分比響應時間。

    併發性:工作中的併發操作,或者同時工作中的線程數或者連接數。

    可擴展性:給系統增加一倍的資源,比如兩倍的cpu數,就可以獲得兩倍的吞吐量,i/o密集型應用 或者是 cpu密集型應用

 

3安裝

    git clone  https://github.com/akopytov/sysbench.git

    cd sysbench-1.0

    ./autogen.sh

    ./configure --prefix=/usr/local/sysbench

    make && make install

    cp usr/local/sysbench/binsysbench  /usr/bin/

 

4測試命令

查找20000以內的素數  /usr/bin/sysbench --test=cpu --cpu-max-prime=20000 --num-threads=4 run

 

4.sysbench測試磁盤IO性能

創建10G的內容,供測試用:    

    sysbench --test=fileio --file-total-size=10G prepare

針對10G文件,做隨機讀寫,測試IO:

    sysbench --test=fileio --file-total-size=10G --file-test-mode=rndrw run

    --file-test-mode 還可以爲

        seqwr:順序寫入

        seqrewq:順序重寫

        seqrd:順序讀取

        rndrd:隨機讀取

        rndwr:隨機寫入

        rndrw:混合隨機讀寫

測試順序讀:

    sysbench --test=fileio --file-total-size=10G --file-test-mode=seqrd run    

測試隨機讀:

    sysbench --test=fileio --file-total-size=10G --file-test-mode=rndrd run    

測試的結果顯示:順序讀取的速度遠遠大於隨機讀,所以好好利用索引+where語句使mysql儘量達成順序度。

 

測試mysql事務性能:

    sysbench --test=/path/to/sysbench-source/tests/db/oltp.lua --mysql-table-engine=innodb --mysql-user=root --db-driver=mysql --mysql-db=test  --oltp-table-size=3000 --mysql-socket=/var/lib/mysql/mysql.sock prepare

 

清除測試數據: 

    sysbench --test=fileio --file-total-size=10G cleanup

 

四,ab壓力測試工具

 

 

五, 具體的優化措施

    

  • 儘量使用可以正確存儲數據的最小數據類型。

  • 簡單就好,整型比字符串操作代價更低,因爲字符集和校對規則(排序規則)使字符串比較比整型比較更復雜,登錄ip保存爲整型。ip保存爲int 用 inet_aton() 和 iner_ntoa()相互切換。

  •  儘量避免null,不利於索引。

 

   1. 表的優化和列類型的選擇

 

       字段類型的優先級:   整型 > date,time > enum > char,   varchar > blob

     int: 定長,沒有國家/地區之分,沒有字符集的差異

     time:定長,運算快,節省空間. 考慮時區,寫sql時不方便 where > ‘2005-10-12’;

     enum:能起來約束值的目的, 內部用整型來存儲,但與char聯查時,內部要經歷串與值的轉化

     Char:定長, 考慮字符集和(排序)校對集,會刪除末尾的空格。密碼的md5值。

     varchar:不定長 要考慮字符集的轉換與排序時的校對集,速度慢.需要一(255字節)到兩個額外的字節保存長度。如果使用ROW_FORMART = FIXED 創建表的的話 varchar使用定長存儲 很浪費空間

     text/Blob 無法使用內存臨時表,會寫入磁盤

        大的字段浪費內存

     避免用NULL 不利於索引,需要用特殊字節標註佔用磁盤空間

     enum列內部是整型存儲 enum列與enum列關聯速度最快,性別學歷配置等建議用此

     表結構的拆分,如核心字段都用int,char,enum等定長結構

     非核心字段,或用到text,超長的varchar,拆出來單放一張表

     如果需要保存精度較高的,參與計算的 可以使用decimal 如果有特別的高的精度,比如小數點後好幾位,可以使用bigint,乘於相應的倍數即可。

 

    

2.表的優化

    1: 定長與變長分離

    如 id int, 佔4個字節, char(4) 佔4個字符長度,也是定長, time 即每一單元值佔的字節是固定的.

    核心且常用字段,宜建成定長,放在一張表.而varchar, text,blob,這種變長字段,適合單放一張表, 用主鍵與核心表關聯起來.

    注意:⚠️ 如果使用ROW_FORMART = FIXED 創建表的的話 varchar使用定長存儲 很浪費空間

             VARCHAR 需要1-2個字節記錄字符串的長度  字符串<= 255 一個字節 > 255 兩個字節

    2:常用字段和不常用字段要分離.

    需要結合網站具體的業務來分析,分析字段的查詢場景,查詢頻度低的字段,單拆出來.

    3:合理添加冗餘字段.

 

   六  索引

        索引 是排好序的,幫助數據庫快速獲取數據的數據結構

        創建索引:

                CREATE [UNIQUE] INDEX indexName on tableName (columename(length));

                ALTER  TABLE tableName  ADD [UNIQUE] INDEX  indexNanme on  columename(length));

        刪除索引:

                DROP INDEX indexName on tableName;

1 .索引優點:

  1.  大大減少服務器需要掃描的數據量

  2.  幫助服務器避免排序和臨時表

  3.  將隨機i/o 變爲順序i/o

  4.  

2. 索引介紹

    B-tree索引,用的是平衡樹 二叉樹 myisam和innodb默認的索引, 排好序的能快速查找的數據結構

  • 在where條件上都加上索引,多列上獨立的索引 可能只導致使用一個索引。

  • 多列上建立索引及聯合索引,並且滿足左前綴要求。

            左前綴要求:從左到右

      index(a,b,c) a,b,c三列上建立了索引,逐個發揮作用,a索引下建立b索引建立c索引 只有依次命中索引,後面的列才能命中索引,否則導致索引不連貫 後面的索引級就不能再使用了。

      連續的where條件 mysql在不影響查詢結果下會自動調優 滿足左前綴規則

            左前綴索引實戰:

    reset query cache;清除mysql的查詢緩存

    alter table goods add index(cat_id,shop_price);

    explain select goods_id,shop_price from goods where cat_id =3 and shop_price>3000;

            explain語句分析sql語句執行情況

                key_len 參數 表示用到的索引個數 一個utf佔3位 所以次數要除以三  比如用12 用到的索引個數就是12/3 等於4

                rows 掃描的行數

                extra using  index 使用索引覆蓋。 

        

    create table index_index (

        -> c1 char(1) not null default '',

        -> c2 char(1) not null default '',

        -> c3 char(1) not null default '',

        -> c4 char(1) not null default '',

        -> c5 char(1) not null default '',

        -> key(c1,c2,c3,c4,c5)    

        -> )engine innodb charset utf8;

    key 建立聯合索引

    

hash索引, memory 默認hash索引,在磁盤上隨機放置數據,無法對範圍進行優 ,無法用到前綴索引 ,必須回行,通過索引拿到數據後還要在表中取到數據

 

myisam和innodb索引的區別:

         innodb的(次索引)索引:

       次級索引指向對主鍵的引用 ,主鍵索引(主索引)上每個二叉樹的葉子節點直接保存索引的值和數據 次級索引上二叉樹葉子節點指向對主鍵的引用

       比如 主鍵索引上 id爲7的二叉樹的葉子節點上保存着此行的所有數據,name的二叉樹上直接就保存着主鍵id值,用過主鍵id直接在主索引就能找到數據。

   聚簇索引:

       像innodb中,主鍵的索引結構中,既存儲了主鍵值,又存儲了行數據,這種結構稱爲”聚簇索引”

       索引的值和此行的數據保存在一起,通過主鍵查詢就能快速定位數據,次索引指向對主鍵的引用,通過次級索引需要查找到主鍵id再從主鍵id找到數據。

       沒有主鍵時 Unique key做主鍵,或者內部生成rowid做主鍵。

       當葉子節點分裂時,葉子節點保存着數據,節點改變性能消耗較大,所以主鍵儘量使用整型並且遞增,如果無規律的就會產生葉的分裂。

   數據量大:

       1字段類型比較大,存儲的數據比較大  

       2字段數量比較多  這時數據存放在磁盤中,每個葉子節點的數據存放在幾個磁盤塊中,跨塊查詢就比較慢

         select id from person order by id; //這時查詢速度比較慢

         select id from person order by id,var //複合索引 id 和 var 葉子節點只存放這主鍵的依賴,並沒有每一行的數據,所以就比較快

    

        myisam的索引:

     myisam的次索引和主索引指向物理行 每個二叉樹上葉子節點都有指向磁盤物理行的指針和此索引的值,所以查找索引其他的數據就是回行查找,在磁盤中查找的效率比較低    

     當葉子節點分裂時,因爲每個葉子節點只保存物理行的指針,消耗的性能就很少

   覆蓋索引:    

      如果查詢的列恰好是索引的一部分,查詢只需要再索引的文件進行,不需要再磁盤上回行查找,查詢速度非常快。

      查詢的結果索引已經覆蓋住,所以叫覆蓋索引,或者索引覆蓋。

 

 

七 高性能索引優化:

 

好的索引:

    查詢頻繁  區分度高  長度小  能覆蓋常用查詢字段

    區分度高和長度小是矛盾的

    查詢中的列是獨立的,不能是表達式的一部分也不能是函數的參數。

某個字段建立索引方式:

    測試: 爲t2表中字段word建立索引

    select count(distinct left(word,1)) / count(*) from t2;

    建立索引的字段截取的長度和總長度的比例 一般達到0.1就能夠接受 如word最大長度爲14 當截取的數字爲4-5時 就能達到0.9時 就按照word的左4位建立索引    

    alert table t2 add index word(word(4));//建立名字爲word的索引 佔用word字段的左4位

左前綴不易區分的列,建立索引:

    如 URL

    1倒序存放 左前綴的區別度就高

    2僞hash效果  crc32()函數來構造一個僞hash列 把字符串的列轉成整型,降低索引的長度

多列索引:

    列的查詢頻率 , 列的區分度。按照業務需求來判斷

大數據量分頁效果:

    從業務上優化  不允許翻到100頁

    limit 查詢是逐行查找 先查找 再跳行 大數據分頁時就有很長的查詢時間

    解決方法,

        1.跳過前面的數據   where id> 100000  limit 50;(前提是id完整 沒有物理刪除)(一般來說 網站的數據是不物理刪除的  只做邏輯刪除)。

        2.延遲關聯 先查詢出滿足的id,再通過id查詢出對應的數據  id是主鍵 百萬級分頁 從6-7秒 優化到1-2秒

          select * from a inner join (select id from a limit 500000,10) as tmp on id=tmp.id;

索引與排序:

    排序可能出現的情況:

    1.覆蓋索引直接在索引上查詢,就是有序的 useing index

    2.先取出數據,形成臨時表做filesort(文件排序,有可能在磁盤上,也有可能在內存中)

    爭取取出來的數據就是有序的,利用索引來排序

    比如:goods表 cat_id 和price 組成聯合索引

        where cat_id =n order_by price 可以利用索引來排序,左前綴規則(using  where) 如果不是聯合索引 就不能索引排序  using filesort

重複索引和冗餘索引:

     重複索引:在同一個列或者順序相同的幾個列上建立多個索引,重複索引沒有任何幫助,增大索引文件

     冗餘索引:2個索引覆蓋的列有重疊  index x(x) index xm(x,m)  x和xm索引重疊,允許存在

索引碎片和維護:

    長期的數據更改中,索引文件和數據文件都會產生空洞,形成碎片

    nop (不產生對數據實質性影響的操作)操作修改表,比如  alert table goods engine inoodb; 會重新規劃數據,表比較大時,非常耗費資源,週期按業務確定

mysql通信協議:

    ‘半雙工’通信,在任一時刻,要麼是由服務器像客戶端發送數據,要麼是客戶端像服務器發送數據,不能同時發生。

    mysql需要等所有的數據都返回給客戶端纔會釋放此查詢佔用的資源,所以增加limit是有效的限制。

 

 

 

九   mysql語句優化:

 

查詢開銷:

    響應時間:服務時間,排隊時間;

    掃描的行數

    返回的行數

查詢慢:等待時間和執行時間

 

1sql語句的時間花在:

    等待時間:

    執行時間:a: 查 ----> 沿着索引查,甚至全表掃描

                      b: 取 ----> 查到行後,把數據取出來(sending data)

 

這兩個時間並非孤立的, 如果單條語句執行的快了,對其他語句的鎖定的也就少了.

 

sql語句的優化思路?

1.不查, 通過業務邏輯來計算,

    比如論壇的註冊會員數,我們可以根據前3個月統計的每天註冊數, 用程序來估算.

2.少查, 儘量精準數據,少取行. 我們觀察新聞網站,評論內容等,一般一次性取列表 10-30條左右.

3.必須要查,儘量走在索引上查詢行.

 

取時, 取儘量少的列.

比如  select * from tableA,  就取出所有列, 不建議.

比如  select * from tableA,tableB, 取出A,B表的所有列.

 

4: 如果定量分析查的多少行,和是否沿着索引查?

 

答: 用explain來分析 explain是mysql優化器對用戶查詢sql進行優化。

      explain  表的讀取順序,數據讀取操作的操作類型,哪些索引可以被使用,實際使用了哪些索引,表之間的引用,每張表有多少行被優化器查詢

explain:

    id :表的讀取順序  查詢的編號

         相同 從上到下讀取,

         不同 從大到小讀取 

         相同又不同 由大到小 從上到下讀取 

    select_type: 查詢類型 

                 simlpe  簡單查詢,不包含子查詢或者union

                 primary 查詢中有複雜的子查詢,這是最外層的查詢,類似於雞蛋殼

                 subquery  select或者where 後中的子查詢

                 derived   衍生查詢 from 後包含的子查詢,mysql會遞歸的執行這些子查詢,放入臨時表中。

                 union  若第二個select 出現在union之後,標記爲union,若union包含在from子句的子查詢中,外層的select被標記爲derived

                 union result 從union表中獲取結果的select 

    table:表名(別名)

 

    type:訪問的類型(重要)     性能由好到差。system > const > eq_ref > ref > rang > index > all 

        all(逐行查找,特別不好)        

        index(掃描所有的索引節點   index )       

        range (通過索引 範圍查詢           between > < = )  

        ref(通過所引直接引用到所有的數據行 where id = 1 )  

        eq_ref(唯一性索引掃描,對每個索引鍵,表中只有一條數據與之匹配 where id = 1)  

        const(表示通過索引一次就找到數據,primary key 或者unique索引,只匹配一次數據就得到) 

        system (表中的數據只有一行)

注意:優化達到range就可以滿足要求了 

 

    possible_keys 可能用到的索引

    key:最終用到的索引 null沒有用到索引,

        如果命中索引覆蓋,則該索引只出現在key中

    key_len:索引中使用的子節數,長度越短越好

         alert table t2 add index word(word(4));//建立名字爲word的索引 佔用word字段的左4位 

    ref : 顯示索引中那個列被使用,可能是個常量,那些列或者長了被用於查找索引列上的值。

    rows :估計找到所需數據可能被掃描的行樹,數據越少越好。

    extra: 

         using index(最好)  表示select使用了covering index 覆蓋索引,避免了訪問數據行,效率比較高。如果同時存在using where 表示索引被用來執行索引鍵值的查找,如果沒有存在,表示索引讀取數據而非執行查找動作。

         using where    

         using  temporary (很差)  使用臨時表保存中間的結果,常見於order by 或者group by 

         using filesort 文件排序(很差) mysql會對數據使用一個外部的索引排序。而不是按照表內的索引順序進行讀取,也是就是mysql中無法利用索引完成的排序操作。

explain誤區:

    explain不產生查詢,複雜的還是要產生查詢(5.6版本就不產生查詢)   explain是執行過程(explain 不是執行過程)

 

 

5:發現掃描大量的數據但是隻返回了很少的行:

    使用覆蓋索引:把需要的列都放在索引中,存儲引擎就不會回行查找。

    改變表結構,比如使用匯總表。

    重寫複雜的查詢。

 

重寫複雜的查詢:

1:把複雜的查詢切分成小查詢(切分查詢)

比如定期刪除數據,如果一次性執行會鎖住很多數據,佔滿整個事務日誌,阻塞很多小的但是有用的查詢。

可以分批量,每次刪除等待一段時間再做下一次刪除,就可以把壓力分佈到很長的時間中,減少服務器的壓力,減少刪除時持有鎖的時間。

 

2:分解關聯查詢:

如查詢某個商品的信息:包含品牌,分類,價格,供應商等,可以分解爲多條查詢,程序匹配。

1讓緩存的效率更高,mysql有自己的查詢緩存,表改變少,就可以重複利用查詢緩存。

2減少鎖競爭。

3應用層關聯,可以對數據庫進行拆分,做到高性能和可擴展性。

4減少冗餘記錄的查詢。

 

in子查詢陷阱:

    select id,name from a where id in ();

    先掃面a中的id,再b表中查詢是否存在,直接掃描了a表中的所有數據。

    用連接查詢

    select id,name from a inner join b on a.id=b.id;

    select id,name from a inner join (select id from b where id =6) as tmp  on tmp.id=b.id;

 

exists查詢:

    in 和 join exists 效率要看業務邏輯,在用mysql的執行計劃分析,不要掃描更多的表 不要零時表 不要文件排序

 

max min 優化技巧:

    select id from a use index(primary) where pid =100 limit 1;

    直接使用主鍵索引,按主鍵索引排序 就取出pid爲100的最小的值 但是不建議這麼做,語義模糊。

 

count 優化技巧:

    count 總行數會緩存到內存中,所以沒有條件的直接查詢就會快

    有條件的count 查詢

    取出大於等於100的個數

    (select count(*) from a) - (select count(*) where id <100);

 

gorup by:

    用於分組統計 不要篩選數據 使用所以避免臨時表和文件排序

 

 

 

mysql主從集羣設置:

    主從:    主服務器建立授權複製賬號,從服務器利用複製賬號監聽主服務器的日誌

        1主服務器建立二進制日誌,每產生語句或者磁盤變化寫進日誌

        2從服務器在主服務器中讀取二進制日誌,形成中繼日誌(relay_log),再寫入

        3保證主從服務器的3306端口互通

    流程:

主服務器配置:

    vim /etc/my.cnf

 

    #開啓二進制日誌,文件名

    log-bin=mysql-bin

 

    #指定日誌格式

    binlog-format=mixed     #statement:語句變化 row:行的變化  mixed:混合的

    

    #配置server_id 唯一的服務器id

    server-id = 153 #一般配置爲ip的最後位

    #建立授權賬號

    mysql -uroot -p

    grant replication client,replication slave on *.* to 'repl'@'47.52.33.73' IDENTIFIED by 'repl123456';

    

    #查看主服務器的狀態,

    #show master status;  從服務器配置需要下面兩個參數

    File:mysql-bin.000003(6位) 顯示出當前的二進制文件

    Posistion:278 顯示出二進制日誌的時間點

 

    #二進制日誌的文件路勁

    cd /usr/local/mysql/data

 

 

#從服務器配置:

    vim /etc/my.cnf

    server-id=200;

    relay-log=mysql-relay

 

    #鏈接主服務器

    mysql -uroot -p

    

 

    #告訴從服務器主服務器的信息                                   主服務器的二進制文件               二進制時間點

    change master to master_host='47.52.111.153',master_user='repl',master_password='repl123456',master_log_file='mysql-bin.000001',master_log_pos=1042;

 

    #查看從服務器的狀態

    show slave status \G;

 

    #重置slave狀態

    reset slave

 

    #啓動slave 開始監聽master的變化

    start slave

 

    #停止slave狀態

    stop slave  

 

 

 

主服務器日誌格式:

    statement  複製語句 :很多行的數據都會變化,用語句的格式

    row        複製磁盤 :修改或者新增一行數據,對其他行沒有影響,直接複製磁盤1行的變化

    mixed      混合的   :語句不通自動選擇混合的格式

 

    

 

    

    

mysql主主複製:

    兩臺服務器能相互複製

    思路:

    2臺服務器都設置二進制日誌和relay-log中繼日誌

    都設置replication 賬號

    都設置對方爲自己的master

   

    配置:

    一主:

    server-id=199

    log-bin=mysql-bin

    binlog-format=mixed

    relay-log=mysql-relay

    grant replication client,replication slave on *.* to 'repl'@'47.52.111.153' IDENTIFIED by 'repl123456';

    

 

    change master to master_host='47.52.33.73',master_user='repl',master_password='repl123456',master_log_file='mysql-bin.000002',master_log_pos=120;

 

 

    二主:

    server-id=200

    log-bin=mysql-bin

    binlog-format=mixed

    relay-log=mysql-relay

    grant replication client,replication slave on *.* to 'repl'@'47.52.33.73' IDENTIFIED by 'repl123456';

 

    change master to master_host='47.52.111.153',master_user='repl',master_password='repl123456',master_log_file='mysql-bin.000002',master_log_pos=858;

 

 

注意:主主複製必須要防範主鍵衝突問題(兩臺服務器的解決方法)    

    global:全局生效 session:是當前鏈接生效

    一臺服務器1357增長  

        set global auto_increment_increment=2;//增長步長

        set global auto_increment_offset=1;//開始增長位

        set session auto_increment_increment=2;

        set session auto_increment_offset=1;

    一臺服務器2468增長

        set global auto_increment_increment=2;

        set global auto_increment_offset=2;

        set session auto_increment_increment=2;

        set session auto_increment_offset=2;

    

    多臺服務器的解決方法:

        業務上解決:設計一個redis,構建global:userid

        每次插入前 incr->global:userid 得到不重複的userid

 

被動主主複製:

    指兩臺服務器地位一樣,但是其中一臺爲只讀,並且業務中也只寫某一臺服務器,用於故障切換

    一臺服務器 配置:

        read-only=on;

 

路由到sql語句上,集羣中間件:

    mysql_proxy

 

 

官方mysql_proxy中間件實現mysql的負載均衡和讀寫分離:

        

    1下載: wget  https://downloads.mysql.com/archives/get/file/mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz

    2解壓:tar axvf

    3幫助文檔  ./bin/mysql-proxy --help-all

 

    4創建連接

    ./bin/mysql-proxy -p 47.52.111.153:4040

    --proxy-backend-addresses=47.52.111.153:3306 #一臺服務器

    --proxy-backend-addresses=47.52.111.153:3306 #另一臺服務器

 

    5連接mysql-proxy

    mysql -h 47.52.111.153 -uroot -p  -P 4040

 

    6 4條插入語句沒有均衡到兩臺服務器上(insert into ):

    均衡:不是指語句單位的均衡,容易帶來數據不一致,指的是連接的均衡。

          100次連接命中到不同服務器上,然後每個連接在相同的數據庫服務器上操作

    

 

    7創建讀寫分離

    ./bin/mysql-proxy

    -b 47.52.111.153:3306  -b是proxy-backend-addresses簡寫

    -r 47.52.111.153:3306  -r是proxy-read-only-backend-address簡寫,註明這是隻讀服務器

    -s /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-spliting.lua  -s是proxy-lua-script簡寫,註明是利用哪個腳本進行讀寫分離  

    -daemon  後臺運行

 

 

 

 

表分區:

    partition 從mysql層來進行分表,而不是從業務層進行分表,mysql存儲時按照規律存放到不同的文件上,但是顯示時還是一張表

 

    範圍分區,創建表的時候指定:

    

        CREATE TABLE topic(

        tid INT PRIMARY KEY AUTO_INCREMENT,

        title CHAR(20) NOT NULL DEFAULT ''

        )ENGINE = INNODB CHARSET utf8

        PARTITION BY RANGE(tid)(

        PARTITION t0 VALUES LESS THAN(10),

        PARTITION t1 VALUES LESS THAN(20),

        PARTITION t2 VALUES LESS THAN(30),

        PARTITION t3 VALUES LESS THAN(MAXVALUE)

        );

    說明:

        表示以替代分區 低於10的放在t0分區 低於20的放在t1分區  MAXVALUE表示常量,指最大的值

    

 

    區域分區:

        1創建一張區域表

        CREATE TABLE AREA(

            aid INT PRIMARY KEY AUTO_INCREMENT,

            zone CHAR(20) NOT NULL DEFAULT ''

        )ENGINE INNODB CHARSET utf8;

 

        2插入數據

        insert into area (zone) values ("北京");

        insert into area (zone) values ("上海");

        insert into area (zone) values ("重慶");

        insert into area (zone) values ("天津");

 

 

        3創建用戶表

        CREATE TABLE USER(

            uid INT  ,

            NAME CHAR(20) NOT NULL DEFAULT '',

            aid INT PRIMARY KEY

        )ENGINE INNODB CHARSET utf8

        PARTITION BY LIST(aid)(

        PARTITION t1 VALUES IN(1),

        PARTITION t2 VALUES IN(2),

        PARTITION t3 VALUES IN(3),

        PARTITION t4 VALUES IN(4)

        );

    

    注:分區列不要爲null 否則mysql會理解爲0

 

    表中有主鍵時,分區鍵也要加入主鍵 形成複合主鍵

    ALTER TABLE `user` ADD PRIMARY KEY(uid,aid);

    ALTER TABLE `user` CHANGE uid uid INT NOT NULL AUTO_INCREMENT;

 

事務:

    原子性:sql語句要麼全部成功要麼全部失敗

    一致性:執行前和執行後的狀態不變

    隔離性:事務進行中其他事務看不到效果

        read uncommitted:未提交度 髒讀

        read committed : 提交度

        repeatable read:可重複讀 一個事務過程中 所有的信息都是事務開始一瞬間的信息,不受其他已提交的事務的影響 這個是mysql默認的隔離級別

        serializable 可串行化,每行數據都

    持久性:事務提交後不能撤銷,只能通過補償性事務抵消效果

    

    髒讀:事務提取到尾提交的數據。

    幻讀:事務讀取某個範圍的記錄時,另一個事物又在該範圍內插入新的記錄,當事務再次讀取該範圍的記錄時會產生幻行。

 

    innodb解決死鎖的方法:將持有最少行級排他鎖的事務進行回滾。

    innodb採用mvcc來支持高併發,通過間隙鎖策略防止幻讀的出現,它不僅鎖定查詢涉及的行,還會對索引中的間隙進行

    

    查看隔離級別:

    SHOW  VARIABLES LIKE '%isolation%'

 

    開啓事務:

    start transaction

    執行

 

    提交

    commit rollback

 

MVCC:

    多版本併發控制,保存數據在某個時間點快照實現的。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章