日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL调优(八):查缺补漏(mysql的锁机制,读写分离,执行计划详解,主从复制原理)

發(fā)布時間:2024/2/28 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL调优(八):查缺补漏(mysql的锁机制,读写分离,执行计划详解,主从复制原理) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

mysql的鎖機制

1、MySQL鎖的基本介紹

? 鎖是計算機協(xié)調(diào)多個進程或線程并發(fā)訪問某一資源的機制。在數(shù)據(jù)庫中,除傳統(tǒng)的 計算資源(如CPU、RAM、I/O等)的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資源。如何保證數(shù)據(jù)并發(fā)訪問的一致性、有效性是所有數(shù)據(jù)庫必須解決的一 個問題,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個重要因素。從這個角度來說,鎖對數(shù)據(jù)庫而言顯得尤其重要,也更加復雜。

? 相對其他數(shù)據(jù)庫而言,MySQL的鎖機制比較簡單,其最 顯著的特點是不同的存儲引擎支持不同的鎖機制。比如,MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認情況下是采用行級鎖。

? 表級鎖:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。
? 行級鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

? 從上述特點可見,很難籠統(tǒng)地說哪種鎖更好,只能就具體應用的特點來說哪種鎖更合適!僅從鎖的角度 來說:表級鎖更適合于以查詢?yōu)橹?#xff0c;只有少量按索引條件更新數(shù)據(jù)的應用,如Web應用;而行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時又有 并發(fā)查詢的應用,如一些在線事務處理(OLTP)系統(tǒng)。

2、MyISAM表鎖

MySQL的表級鎖有兩種模式:表共享讀鎖(Table Read Lock)表獨占寫鎖(Table Write Lock)

對MyISAM表的讀操作,不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;對 MyISAM表的寫操作,則會阻塞其他用戶對同一表的讀和寫操作;MyISAM表的讀操作與寫操作之間,以及寫操作之間是串行的!

建表語句:

CREATE TABLE `mylock` (`id` int(11) NOT NULL AUTO_INCREMENT,`NAME` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;INSERT INTO `mylock` (`id`, `NAME`) VALUES ('1', 'a'); INSERT INTO `mylock` (`id`, `NAME`) VALUES ('2', 'b'); INSERT INTO `mylock` (`id`, `NAME`) VALUES ('3', 'c'); INSERT INTO `mylock` (`id`, `NAME`) VALUES ('4', 'd');

MyISAM寫鎖阻塞讀的案例:

? 當一個線程獲得對一個表的寫鎖之后,只有持有鎖的線程可以對表進行更新操作。其他線程的讀寫操作都會等待,直到鎖釋放為止。

session1session2
獲取表的write鎖定
lock table mylock write;
當前session對表的查詢,插入,更新操作都可以執(zhí)行
select * from mylock;
insert into mylock values(5,‘e’);
當前session對表的查詢會被阻塞
select * from mylock;
釋放鎖:
unlock tables;
當前session能夠立刻執(zhí)行,并返回對應結(jié)果

MyISAM讀阻塞寫的案例:

? 一個session使用lock table給表加讀鎖,這個session可以鎖定表中的記錄,但更新和訪問其他表都會提示錯誤,同時,另一個session可以查詢表中的記錄,但更新就會出現(xiàn)鎖等待。

session1session2
獲得表的read鎖定
lock table mylock read;
當前session可以查詢該表記錄:
select * from mylock;
當前session可以查詢該表記錄:
select * from mylock;
當前session不能查詢沒有鎖定的表
select * from person
Table ‘person’ was not locked with LOCK TABLES
當前session可以查詢或者更新未鎖定的表
select * from mylock
insert into person values(1,‘zhangsan’);
當前session插入或者更新表會提示錯誤
insert into mylock values(6,‘f’)
Table ‘mylock’ was locked with a READ lock and can’t be updated
update mylock set name=‘a(chǎn)a’ where id = 1;
Table ‘mylock’ was locked with a READ lock and can’t be updated
當前session插入數(shù)據(jù)會等待獲得鎖
insert into mylock values(6,‘f’);
釋放鎖
unlock tables;
獲得鎖,更新成功

注意:

MyISAM在執(zhí)行查詢語句之前,會自動給涉及的所有表加讀鎖,在執(zhí)行更新操作前,會自動給涉及的表加寫鎖,這個過程并不需要用戶干預,因此用戶一般不需要使用命令來顯式加鎖,上例中的加鎖時為了演示效果。

MyISAM的并發(fā)插入問題

MyISAM表的讀和寫是串行的,這是就總體而言的,在一定條件下,MyISAM也支持查詢和插入操作的并發(fā)執(zhí)行

session1session2
獲取表的read local鎖定
lock table mylock read local
當前session不能對表進行更新或者插入操作
insert into mylock values(6,‘f’)
Table ‘mylock’ was locked with a READ lock and can’t be updated
update mylock set name=‘a(chǎn)a’ where id = 1;
Table ‘mylock’ was locked with a READ lock and can’t be updated
其他session可以查詢該表的記錄
select* from mylock
當前session不能查詢沒有鎖定的表
select * from person
Table ‘person’ was not locked with LOCK TABLES
其他session可以進行插入操作,但是更新會阻塞
update mylock set name = ‘a(chǎn)a’ where id = 1;
當前session不能訪問其他session插入的記錄;
釋放鎖資源:unlock tables當前session獲取鎖,更新操作完成
當前session可以查看其他session插入的記錄

可以通過檢查table_locks_waited和table_locks_immediate狀態(tài)變量來分析系統(tǒng)上的表鎖定爭奪:

mysql> show status like 'table%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Table_locks_immediate | 352 | | Table_locks_waited | 2 | +-----------------------+-------+ --如果Table_locks_waited的值比較高,則說明存在著較嚴重的表級鎖爭用情況。

InnoDB鎖

1、事務及其ACID屬性

事務是由一組SQL語句組成的邏輯處理單元,事務具有4屬性,通常稱為事務的ACID屬性。

原子性(Actomicity):事務是一個原子操作單元,其對數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。
一致性(Consistent):在事務開始和完成時,數(shù)據(jù)都必須保持一致狀態(tài)。
隔離性(Isolation):數(shù)據(jù)庫系統(tǒng)提供一定的隔離機制,保證事務在不受外部并發(fā)操作影響的“獨立”環(huán)境執(zhí)行。
持久性(Durable):事務完成之后,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。

2、并發(fā)事務帶來的問題

相對于串行處理來說,并發(fā)事務處理能大大增加數(shù)據(jù)庫資源的利用率,提高數(shù)據(jù)庫系統(tǒng)的事務吞吐量,從而可以支持更多用戶的并發(fā)操作,但與此同時,會帶來一下問題:

臟讀: 一個事務正在對一條記錄做修改,在這個事務并提交前,這條記錄的數(shù)據(jù)就處于不一致狀態(tài);這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“臟”的數(shù)據(jù),并據(jù)此做進一步的處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被形象地叫做“臟讀”

不可重復讀:一個事務在讀取某些數(shù)據(jù)已經(jīng)發(fā)生了改變、或某些記錄已經(jīng)被刪除了!這種現(xiàn)象叫做“不可重復讀”。

幻讀: 一個事務按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀”

上述出現(xiàn)的問題都是數(shù)據(jù)庫讀一致性的問題,可以通過事務的隔離機制來進行保證。

數(shù)據(jù)庫的事務隔離越嚴格,并發(fā)副作用就越小,但付出的代價也就越大,因為事務隔離本質(zhì)上就是使事務在一定程度上串行化,需要根據(jù)具體的業(yè)務需求來決定使用哪種隔離級別

臟讀不可重復讀幻讀
read uncommitted
read committed
repeatable read
serializable

可以通過檢查InnoDB_row_lock狀態(tài)變量來分析系統(tǒng)上的行鎖的爭奪情況:

mysql> show status like 'innodb_row_lock%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | Innodb_row_lock_current_waits | 0 | | Innodb_row_lock_time | 18702 | | Innodb_row_lock_time_avg | 18702 | | Innodb_row_lock_time_max | 18702 | | Innodb_row_lock_waits | 1 | +-------------------------------+-------+ --如果發(fā)現(xiàn)鎖爭用比較嚴重,如InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比較高

3、InnoDB的行鎖模式及加鎖方法

? 共享鎖(s):又稱讀鎖。允許一個事務去讀一行,阻止其他事務獲得相同數(shù)據(jù)集的排他鎖。若事務T對數(shù)據(jù)對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。
? 排他鎖(x):又稱寫鎖。允許獲取排他鎖的事務更新數(shù)據(jù),阻止其他事務取得相同的數(shù)據(jù)集共享讀鎖和排他寫鎖。若事務T對數(shù)據(jù)對象A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。

? mysql InnoDB引擎默認的修改數(shù)據(jù)語句:update,delete,insert都會自動給涉及到的數(shù)據(jù)加上排他鎖,select語句默認不會加任何鎖類型,如果加排他鎖可以使用select …for update語句,加共享鎖可以使用select … lock in share mode語句。所以加過排他鎖的數(shù)據(jù)行在其他事務種是不能修改數(shù)據(jù)的,也不能通過for update和lock in share mode鎖的方式查詢數(shù)據(jù),但可以直接通過select …from…查詢數(shù)據(jù),因為普通查詢沒有任何鎖機制。

InnoDB行鎖實現(xiàn)方式

? InnoDB行鎖是通過給索引上的索引項加鎖來實現(xiàn)的,這一點MySQL與Oracle不同,后者是通過在數(shù)據(jù)塊中對相應數(shù)據(jù)行加鎖來實現(xiàn)的。InnoDB這種行鎖實現(xiàn)特點意味著:只有通過索引條件檢索數(shù)據(jù),InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!

1、在不通過索引條件查詢的時候,innodb使用的是表鎖而不是行鎖

create table tab_no_index(id int,name varchar(10)) engine=innodb; insert into tab_no_index values(1,'1'),(2,'2'),(3,'3'),(4,'4'); session1session2
set autocommit=0
select * from tab_no_index where id = 1;
set autocommit=0
select * from tab_no_index where id =2
select * from tab_no_index where id = 1 for update
select * from tab_no_index where id = 2 for update;

session1只給一行加了排他鎖,但是session2在請求其他行的排他鎖的時候,會出現(xiàn)鎖等待。原因是在沒有索引的情況下,innodb只能使用表鎖。

2、創(chuàng)建帶索引的表進行條件查詢,innodb使用的是行鎖

create table tab_with_index(id int,name varchar(10)) engine=innodb; alter table tab_with_index add index id(id); insert into tab_with_index values(1,'1'),(2,'2'),(3,'3'),(4,'4'); session1session2
set autocommit=0
select * from tab_with_indexwhere id = 1;
set autocommit=0
select * from tab_with_indexwhere id =2
select * from tab_with_indexwhere id = 1 for update
select * from tab_with_indexwhere id = 2 for update;

3、由于mysql的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現(xiàn)沖突的。

alter table tab_with_index drop index id; insert into tab_with_index values(1,'4'); session1session2
set autocommit=0set autocommit=0
select * from tab_with_index where id = 1 and name=‘1’ for update
select * from tab_with_index where id = 1 and name=‘4’ for update
雖然session2訪問的是和session1不同的記錄,但是因為使用了相同的索引,所以需要等待鎖

總結(jié)

對于MyISAM的表鎖,主要討論了以下幾點:
(1)共享讀鎖(S)之間是兼容的,但共享讀鎖(S)與排他寫鎖(X)之間,以及排他寫鎖(X)之間是互斥的,也就是說讀和寫是串行的。
(2)在一定條件下,MyISAM允許查詢和插入并發(fā)執(zhí)行,我們可以利用這一點來解決應用中對同一表查詢和插入的鎖爭用問題。
(3)MyISAM默認的鎖調(diào)度機制是寫優(yōu)先,這并不一定適合所有應用,用戶可以通過設置LOW_PRIORITY_UPDATES參數(shù),或在INSERT、UPDATE、DELETE語句中指定LOW_PRIORITY選項來調(diào)節(jié)讀寫鎖的爭用。
(4)由于表鎖的鎖定粒度大,讀寫之間又是串行的,因此,如果更新操作較多,MyISAM表可能會出現(xiàn)嚴重的鎖等待,可以考慮采用InnoDB表來減少鎖沖突。

對于InnoDB表,本文主要討論了以下幾項內(nèi)容:
(1)InnoDB的行鎖是基于索引實現(xiàn)的,如果不通過索引訪問數(shù)據(jù),InnoDB會使用表鎖。
(2)在不同的隔離級別下,InnoDB的鎖機制和一致性讀策略不同。

在了解InnoDB鎖特性后,用戶可以通過設計和SQL調(diào)整等措施減少鎖沖突和死鎖,包括:

  • 盡量使用較低的隔離級別; 精心設計索引,并盡量使用索引訪問數(shù)據(jù),使加鎖更精確,從而減少鎖沖突的機會;
  • 選擇合理的事務大小,小事務發(fā)生鎖沖突的幾率也更小;
  • 給記錄集顯式加鎖時,最好一次性請求足夠級別的鎖。比如要修改數(shù)據(jù)的話,最好直接申請排他鎖,而不是先申請共享鎖,修改時再請求排他鎖,這樣容易產(chǎn)生死鎖;
  • 不同的程序訪問一組表時,應盡量約定以相同的順序訪問各表,對一個表而言,盡可能以固定的順序存取表中的行。這樣可以大大減少死鎖的機會;
  • 盡量用相等條件訪問數(shù)據(jù),這樣可以避免間隙鎖對并發(fā)插入的影響; 不要申請超過實際需要的鎖級別;除非必須,查詢時不要顯示加鎖;
  • 對于一些特定的事務,可以使用表鎖來提高處理速度或減少死鎖的可能。

mysql讀寫分離

1、讀寫分離的介紹

? MySQL讀寫分離基本原理是讓master數(shù)據(jù)庫處理寫操作,slave數(shù)據(jù)庫處理讀操作。master將寫操作的變更同步到各個slave節(jié)點。

? MySQL讀寫分離能提高系統(tǒng)性能的原因在于:

? 1、物理服務器增加,機器處理能力提升。拿硬件換性能。

? 2、主從只負責各自的讀和寫,極大程度緩解X鎖和S鎖爭用。

? 3、slave可以配置myiasm引擎,提升查詢性能以及節(jié)約系統(tǒng)開銷。

? 4、master直接寫是并發(fā)的,slave通過主庫發(fā)送來的binlog恢復數(shù)據(jù)是異步。

? 5、slave可以單獨設置一些參數(shù)來提升其讀的性能。

? 6、增加冗余,提高可用性。

2、讀寫分離的配置

1、硬件配置
master 192.168.85.11 slave 192.168.85.12 proxy 192,168.85.14
2、首先在master和slave上配置主從復制
3、進行proxy的相關(guān)配置
#1、下載mysql-proxy https://downloads.mysql.com/archives/proxy/#downloads #2、上傳軟件到proxy的機器 直接通過xftp進行上傳 #3、解壓安裝包 tar -zxvf mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz #4、修改解壓后的目錄 mv mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit mysql-proxy #5、進入mysql-proxy的目錄 cd mysql-proxy #6、創(chuàng)建目錄 mkdir conf mkdir logs #7、添加環(huán)境變量 #打開/etc/profile文件 vi /etc/profile #在文件的最后面添加一下命令 export PATH=$PATH:/root/mysql-proxy/bin #8、執(zhí)行命令讓環(huán)境變量生效 source /etc/profile #9、進入conf目錄,創(chuàng)建文件并添加一下內(nèi)容 vi mysql-proxy.conf 添加內(nèi)容 [mysql-proxy] user=root proxy-address=192.168.85.14:4040 proxy-backend-addresses=192.168.85.11:3306 proxy-read-only-backend-addresses=192.168.85.12:3306 proxy-lua-script=/root/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua log-file=/root/mysql-proxy/logs/mysql-proxy.log log-level=debug daemon=true #10、開啟mysql-proxy mysql-proxy --defaults-file=/root/mysql-proxy/conf/mysql-proxy.conf #11、查看是否安裝成功,打開日志文件 cd /root/mysql-proxy/logs tail -100 mysql-proxy.log #內(nèi)容如下:表示安裝成功 2019-10-11 21:49:41: (debug) max open file-descriptors = 1024 2019-10-11 21:49:41: (message) proxy listening on port 192.168.85.14:4040 2019-10-11 21:49:41: (message) added read/write backend: 192.168.85.11:3306 2019-10-11 21:49:41: (message) added read-only backend: 192.168.85.12:3306 2019-10-11 21:49:41: (debug) now running as user: root (0/0)
4、進行連接
#mysql的命令行會出現(xiàn)無法連接的情況,所以建議使用客戶端 mysql -uroot -p123 -h192.168.85.14 -P 4040

mysql執(zhí)行計劃

? 在企業(yè)的應用場景中,為了知道優(yōu)化SQL語句的執(zhí)行,需要查看SQL語句的具體執(zhí)行過程,以加快SQL語句的執(zhí)行效率。

? 可以使用explain+SQL語句來模擬優(yōu)化器執(zhí)行SQL查詢語句,從而知道m(xù)ysql是如何處理sql語句的。

? 官網(wǎng)地址: https://dev.mysql.com/doc/refman/5.5/en/explain-output.html

1、執(zhí)行計劃中包含的信息

ColumnMeaning
idThe SELECT identifier
select_typeThe SELECT type
tableThe table for the output row
partitionsThe matching partitions
typeThe join type
possible_keysThe possible indexes to choose
keyThe index actually chosen
key_lenThe length of the chosen key
refThe columns compared to the index
rowsEstimate of rows to be examined
filteredPercentage of rows filtered by table condition
extraAdditional information

id

select查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行select子句或者操作表的順序

id號分為三種情況:

? 1、如果id相同,那么執(zhí)行順序從上到下

explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.losal and sg.hisal;

? 2、如果id不同,如果是子查詢,id的序號會遞增,id值越大優(yōu)先級越高,越先被執(zhí)行

explain select * from emp e where e.deptno in (select d.deptno from dept d where d.dname = 'SALES');

? 3、id相同和不同的,同時存在:相同的可以認為是一組,從上往下順序執(zhí)行,在所有組中,id值越大,優(yōu)先級越高,越先執(zhí)行

explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.losal and sg.hisal where e.deptno in (select d.deptno from dept d where d.dname = 'SALES');

select_type

主要用來分辨查詢的類型,是普通查詢還是聯(lián)合查詢還是子查詢

select_type ValueMeaning
SIMPLESimple SELECT (not using UNION or subqueries)
PRIMARYOutermost SELECT
UNIONSecond or later SELECT statement in a UNION
DEPENDENT UNIONSecond or later SELECT statement in a UNION, dependent on outer query
UNION RESULTResult of a UNION.
SUBQUERYFirst SELECT in subquery
DEPENDENT SUBQUERYFirst SELECT in subquery, dependent on outer query
DERIVEDDerived table
UNCACHEABLE SUBQUERYA subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
UNCACHEABLE UNIONThe second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)
--sample:簡單的查詢,不包含子查詢和union explain select * from emp;--primary:查詢中若包含任何復雜的子查詢,最外層查詢則被標記為Primary explain select staname,ename supname from (select ename staname,mgr from emp) t join emp on t.mgr=emp.empno ;--union:若第二個select出現(xiàn)在union之后,則被標記為union explain select * from emp where deptno = 10 union select * from emp where sal >2000;--dependent union:跟union類似,此處的depentent表示union或union all聯(lián)合而成的結(jié)果會受外部表影響 explain select * from emp e where e.empno in ( select empno from emp where deptno = 10 union select empno from emp where sal >2000)--union result:從union表獲取結(jié)果的select explain select * from emp where deptno = 10 union select * from emp where sal >2000;--subquery:在select或者where列表中包含子查詢 explain select * from emp where sal > (select avg(sal) from emp) ;--dependent subquery:subquery的子查詢要受到外部表查詢的影響 explain select * from emp e where e.deptno in (select distinct deptno from dept);--DERIVED: from子句中出現(xiàn)的子查詢,也叫做派生類, explain select staname,ename supname from (select ename staname,mgr from emp) t join emp on t.mgr=emp.empno ;--UNCACHEABLE SUBQUERY:表示使用子查詢的結(jié)果不能被緩存explain select * from emp where empno = (select empno from emp where deptno=@@sort_buffer_size);--uncacheable union:表示union的查詢結(jié)果不能被緩存:sql語句未驗證

table

對應行正在訪問哪一個表,表名或者別名,可能是臨時表或者union合并結(jié)果集
1、如果是具體的表名,則表明從實際的物理表中獲取數(shù)據(jù),當然也可以是表的別名

? 2、表名是derivedN的形式,表示使用了id為N的查詢產(chǎn)生的衍生表

? 3、當有union result的時候,表名是union n1,n2等的形式,n1,n2表示參與union的id

type

type顯示的是訪問類型,訪問類型表示我是以何種方式去訪問我們的數(shù)據(jù),最容易想的是全表掃描,直接暴力的遍歷一張表去尋找需要的數(shù)據(jù),效率非常低下,訪問的類型有很多,效率從最好到最壞依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般情況下,得保證查詢至少達到range級別,最好能達到ref

--all:全表掃描,一般情況下出現(xiàn)這樣的sql語句而且數(shù)據(jù)量比較大的話那么就需要進行優(yōu)化。 explain select * from emp;--index:全索引掃描這個比all的效率要好,主要有兩種情況,一種是當前的查詢時覆蓋索引,即我們需要的數(shù)據(jù)在索引中就可以索取,或者是使用了索引進行排序,這樣就避免數(shù)據(jù)的重排序 explain select empno from emp;--range:表示利用索引查詢的時候限制了范圍,在指定范圍內(nèi)進行查詢,這樣避免了index的全索引掃描,適用的操作符: =, <>, >, >=, <, <=, IS NULL, BETWEEN, LIKE, or IN() explain select * from emp where empno between 7000 and 7500;--index_subquery:利用索引來關(guān)聯(lián)子查詢,不再掃描全表 explain select * from emp where emp.job in (select job from t_job);--unique_subquery:該連接類型類似與index_subquery,使用的是唯一索引explain select * from emp e where e.deptno in (select distinct deptno from dept);--index_merge:在查詢過程中需要多個索引組合使用,沒有模擬出來--ref_or_null:對于某個字段即需要關(guān)聯(lián)條件,也需要null值的情況下,查詢優(yōu)化器會選擇這種訪問方式 explain select * from emp e where e.mgr is null or e.mgr=7369;--ref:使用了非唯一性索引進行數(shù)據(jù)的查找create index idx_3 on emp(deptno);explain select * from emp e,dept d where e.deptno =d.deptno;--eq_ref :使用唯一性索引進行數(shù)據(jù)查找 explain select * from emp,emp2 where emp.empno = emp2.empno;--const:這個表至多有一個匹配行, explain select * from emp where empno = 7369;--system:表只有一行記錄(等于系統(tǒng)表),這是const類型的特例,平時不會出現(xiàn)

possible_keys

? 顯示可能應用在這張表中的索引,一個或多個,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

key

? 實際使用的索引,如果為null,則沒有使用索引,查詢中若使用了覆蓋索引,則該索引和查詢的select字段重疊。

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

key_len

表示索引中使用的字節(jié)數(shù),可以通過key_len計算查詢中使用的索引長度,在不損失精度的情況下長度越短越好。

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

ref

顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù)

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

rows

根據(jù)表的統(tǒng)計信息及索引使用情況,大致估算出找出所需記錄需要讀取的行數(shù),此參數(shù)很重要,直接反應的sql找了多少數(shù)據(jù),在完成目的的情況下越少越好

explain select * from emp;

extra

包含額外的信息。

--using filesort:說明mysql無法利用索引進行排序,只能利用排序算法進行排序,會消耗額外的位置 explain select * from emp order by sal;--using temporary:建立臨時表來保存中間結(jié)果,查詢完成之后把臨時表刪除 explain select ename,count(*) from emp where deptno = 10 group by ename;--using index:這個表示當前的查詢時覆蓋索引的,直接從索引中讀取數(shù)據(jù),而不用訪問數(shù)據(jù)表。如果同時出現(xiàn)using where 表名索引被用來執(zhí)行索引鍵值的查找,如果沒有,表面索引被用來讀取數(shù)據(jù),而不是真的查找 explain select deptno,count(*) from emp group by deptno limit 10;--using where:使用where進行條件過濾 explain select * from t_user where id = 1;--using join buffer:使用連接緩存,情況沒有模擬出來--impossible where:where語句的結(jié)果總是false explain select * from emp where empno = 7469;

mysql主從復制原理

0、為什么需要主從復制?

1、在業(yè)務復雜的系統(tǒng)中,有這么一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那么就很影響運行中的業(yè)務,使用主從復制,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現(xiàn)了鎖表的情景,通過讀從庫也可以保證業(yè)務的正常運作。

2、做數(shù)據(jù)的熱備

3、架構(gòu)的擴展。業(yè)務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。

1、什么是mysql的主從復制?

? MySQL 主從復制是指數(shù)據(jù)可以從一個MySQL數(shù)據(jù)庫服務器主節(jié)點復制到一個或多個從節(jié)點。MySQL 默認采用異步復制方式,這樣從節(jié)點不用一直訪問主服務器來更新自己的數(shù)據(jù),數(shù)據(jù)的更新可以在遠程連接上進行,從節(jié)點可以復制主數(shù)據(jù)庫中的所有數(shù)據(jù)庫或者特定的數(shù)據(jù)庫,或者特定的表。

2、mysql復制原理

原理:

? (1)master服務器將數(shù)據(jù)的改變記錄二進制binlog日志,當master上的數(shù)據(jù)發(fā)生改變時,則將其改變寫入二進制日志中;

? (2)slave服務器會在一定時間間隔內(nèi)對master二進制日志進行探測其是否發(fā)生改變,如果發(fā)生改變,則開始一個I/OThread請求master二進制事件

? (3)同時主節(jié)點為每個I/O線程啟動一個dump線程,用于向其發(fā)送二進制事件,并保存至從節(jié)點本地的中繼日志中,從節(jié)點將啟動SQL線程從中繼日志中讀取二進制日志,在本地重放,使得其數(shù)據(jù)和主節(jié)點的保持一致,最后I/OThread和SQLThread將進入睡眠狀態(tài),等待下一次被喚醒。

也就是說:
  • 從庫會生成兩個線程,一個I/O線程,一個SQL線程;
  • I/O線程會去請求主庫的binlog,并將得到的binlog寫到本地的relay-log(中繼日志)文件中;
  • 主庫會生成一個log dump線程,用來給從庫I/O線程傳binlog;
  • SQL線程,會讀取relay log文件中的日志,并解析成sql語句逐一執(zhí)行;
注意:

1–master將操作語句記錄到binlog日志中,然后授予slave遠程連接的權(quán)限(master一定要開啟binlog二進制日志功能;通常為了數(shù)據(jù)安全考慮,slave也開啟binlog功能)。
2–slave開啟兩個線程:IO線程和SQL線程。其中:IO線程負責讀取master的binlog內(nèi)容到中繼日志relay log里;SQL線程負責從relay log日志里讀出binlog內(nèi)容,并更新到slave的數(shù)據(jù)庫里,這樣就能保證slave數(shù)據(jù)和master數(shù)據(jù)保持一致了。
3–Mysql復制至少需要兩個Mysql的服務,當然Mysql服務可以分布在不同的服務器上,也可以在一臺服務器上啟動多個服務。
4–Mysql復制最好確保master和slave服務器上的Mysql版本相同(如果不能滿足版本一致,那么要保證master主節(jié)點的版本低于slave從節(jié)點的版本)
5–master和slave兩節(jié)點間時間需同步

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JqbjGUTC-1593568641510)(e:\lian\oracle\mysql\主從原理.png)]

具體步驟:

1、從庫通過手工執(zhí)行change master to 語句連接主庫,提供了連接的用戶一切條件(user 、password、port、ip),并且讓從庫知道,二進制日志的起點位置(file名 position 號); start slave

2、從庫的IO線程和主庫的dump線程建立連接。

3、從庫根據(jù)change master to 語句提供的file名和position號,IO線程向主庫發(fā)起binlog的請求。

4、主庫dump線程根據(jù)從庫的請求,將本地binlog以events的方式發(fā)給從庫IO線程。

5、從庫IO線程接收binlog events,并存放到本地relay-log中,傳送過來的信息,會記錄到master.info中

6、從庫SQL線程應用relay-log,并且把應用過的記錄到relay-log.info中,默認情況下,已經(jīng)應用過的relay 會自動被清理purge

3、mysql主從形式

(一)一主一從
(二)主主復制
(三)一主多從
(四)多主一從
(五)聯(lián)級復制

4、mysql主從同步延時分析

? mysql的主從復制都是單線程的操作,主庫對所有DDL和DML產(chǎn)生的日志寫進binlog,由于binlog是順序?qū)?#xff0c;所以效率很高,slave的sql thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨機的,不是順序,所以成本要高很多,另一方面,由于sql thread也是單線程的,當主庫的并發(fā)較高時,產(chǎn)生的DML數(shù)量超過slave的SQL thread所能處理的速度,或者當slave中有大型query語句產(chǎn)生了鎖等待,那么延時就產(chǎn)生了。

? 解決方案:

? 1.業(yè)務的持久化層的實現(xiàn)采用分庫架構(gòu),mysql服務可平行擴展,分散壓力。

? 2.單個庫讀寫分離,一主多從,主寫從讀,分散壓力。這樣從庫壓力比主庫高,保護主庫。

? 3.服務的基礎架構(gòu)在業(yè)務和mysql之間加入memcache或者redis的cache層。降低mysql的讀壓力。

? 4.不同業(yè)務的mysql物理上放在不同機器,分散壓力。

? 5.使用比主庫更好的硬件設備作為slave,mysql壓力小,延遲自然會變小。

? 6.使用更加強勁的硬件設備

mysql5.7之后使用MTS并行復制技術(shù),永久解決復制延時問題------自學

總結(jié)

以上是生活随笔為你收集整理的MySQL调优(八):查缺补漏(mysql的锁机制,读写分离,执行计划详解,主从复制原理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。