史上最詳細的網站優化系列(一)mysql優化1

一、mysql優化概述

方針:

① 存儲層:數據表”存儲引擎”選取、字段類型選取、逆範式(3範式)
② 設計層:索引、分區/分表、存儲過程,sql語句的優化
③ 架構層:分佈式部署(集羣)(讀寫分離),需要增加硬件
④ sql語句層:結果一樣的情況下,要選擇效率高、速度快、節省資源的sql語句執行

二、存儲引擎的選擇

1、存儲引擎介紹

熟悉的存儲引擎:Myisam、innodb memory
(1)什麼是存儲引擎?
數據表存儲數據的一種格式。
數據存儲在不同的格式裏邊,該格式體現的特性也是不一樣的。例如innodb存儲引擎的特性有支持事務、支持行級鎖,mysiam支持的特性有壓縮機制等。
MySQL中的數據是通過各種不同的技術(格式)存儲在文件(或者內存)中的。技術和本身的特性就稱爲"存儲引擎"。
(2)存儲引擎的理解:
現實生活中,樓房、平房就是具體存儲人的存儲引擎,樓房、平房有自己獨特的技術特性
例如樓房有樓梯、電梯、平房可以自己打井喝水等。
在這裏插入圖片描述
(3)存儲引擎所處的位置:
存儲引擎,處於MySql服務器的最底層,直接存儲數據,導致上層的操作,依賴於存儲引擎的選擇。
客戶端-》網絡連接層-》業務邏輯層(編譯,優化,執行SQL)-》存儲引擎層
在這裏插入圖片描述
查看當前mysql支持的存儲引擎列表:

show engines

打開cmd,輸入mysql -uroot -p123456(u、p後面是你的mysql的用戶名和密碼,如不能進入mysql則配置下環境變量,如下
右擊 計算機——屬性——高級系統設置——高級->環境變量->系統變量
選擇PATH,在其後面添加:你的mysql文件夾路徑/bin (如:D:\phpStudy\MySQL\bin)
PATH=…;D:\phpStudy\MySQL\binn (注意爲追加,不是覆蓋所以放到最後前面以;作爲隔離)
)進入mysql控制檯,輸入上面命令
在這裏插入圖片描述
(4)常用存儲引擎:
① Myisam:表鎖,全文索引
② Innodb:行(記錄)鎖,事務(回滾),外鍵
③ Memory:內存存儲引擎,速度快、數據容易丟失(實用性太差幾乎用不到,特別現在有了nosql的出現)

2、innodb存儲引擎

在>=5.5 版本中默認的存儲引擎,MySql推薦使用的存儲引擎。提供事務,行級鎖定,存儲引擎。
事務安全型存儲引擎,更加註重數據的完整性和安全性。
(1)存儲格式:
innodb存儲引擎 每個數據表有單獨的“結構文件” *.frm
數據,索引集中存儲,存儲於同一個表空間文件中ibdata1。
ibdata1就是InnoDB表的共享存儲空間,默認innodb所有表的數據都在一個ibdata1裏。
創建innodb表後,存在文件如下:

create table t1(id int,name varchar(32)) engine innodb charset utf8;

先查看數據庫
在這裏插入圖片描述

打開數據庫並創建表t1
在這裏插入圖片描述
.frm表結構文件。

在這裏插入圖片描述
innodb表空間文件:存儲innodb的數據和索引。
ibdata1
在這裏插入圖片描述
默認,所有的 innodb表的數據和索引在同一個表空間文件中,
通過配置可以達到每個innodb的表對應一個表空間文件。

show  variables   like 'innodb_file_per_table%';

在這裏插入圖片描述
開啓該配置:

set  global  innodb_file_per_table=1;

在這裏插入圖片描述
創建一個innodbd的表進行測試使用。
在這裏插入圖片描述
查看錶對應的文件自己獨立的“數據/索引”文件
在這裏插入圖片描述
系統配置參數innodb_file_per_table後期無論發生任何變化,t2都有自己獨立的“數據/索引”文件。
注意:相比較之下,使用獨佔表空間的效率以及性能會更高一點。
注意:innodb數據表不能直接進行文件的複製/粘貼進行備份還原,可以使用如下指令:

備份數據庫的指令

 mysqldump  -uroot -p密碼  數據庫名字 > f:/文件名稱.sql  [備份]

需要到有mysqldump文件的目錄操作
在這裏插入圖片描述
備份數據庫
在這裏插入圖片描述
成功後備份文件php.sql會出現在e盤
在這裏插入圖片描述
還原數據庫

mysql -uroot  -p密碼 數據庫   <  f:/文件名稱.sql  [還原]

在這裏插入圖片描述
備份文件php.sql還原到demo數據庫
在這裏插入圖片描述
(2)數據是按照主鍵順序存儲。
該innodb數據表,數據的寫入順序 與 存儲的順序不一致,需要按照主鍵的順序把記錄擺放到對應的位置上去,速度比Myisam的要稍慢。

create table t3(
id int primary key auto_increment,
name varchar(32) not null
)engine innodb charset utf8;
insert into t3 values(223,'劉備'),(12,'張飛'),(162,'張聊'),(1892,'網飛');

給innodb數據表寫入4條記錄信息(主鍵id值順序不同)
插入時做排序工作,效率低。
在這裏插入圖片描述
遇到中文字符串無法寫入到數據表中問題,改變原有數據庫的編碼方式

set character_set_database=utf8;
set character_set_server=utf8;
set character_set_client=gbk;
set character_set_connection=gbk;
set character_set_results=gbk;

查看編碼狀態

show variables like'%char%';

在這裏插入圖片描述
刪除原數據表重新測試:
在這裏插入圖片描述
(3)併發處理:
擅長處理併發的。
行級鎖定(row-level locking),實現了行級鎖定,在一定情況下,可以選擇行級鎖來提升併發性,也支持表級鎖定,innodb根據操作選擇。
鎖機制:
當客戶端操作表(記錄)時,爲了保證操作的隔離性(多個客戶端操作不能相互影響),通過加鎖來處理。
操作方面:
讀鎖:讀操作時增加的鎖,也叫共享鎖,S-lock。特徵是所有人都只可以讀,只有釋放鎖之後纔可以寫。
寫鎖:寫操作時增加的鎖,也叫獨佔鎖或排他鎖,X-lock。特徵,只有鎖表的客戶可以操作(讀寫)這個表,其他客戶讀都不能讀。
辦公室開會鎖上門。
鎖定粒度(範圍)
表級鎖:開銷小,加鎖快,發生鎖衝突的概率最高,併發度最低。myisam和innodb都支持。
行級鎖:開銷大,加鎖慢,發生鎖衝突的概率最低,併發度也最高。innodb支持

3、MyISAM存儲引擎

<=5.5mysql默認的存儲引擎。
(ISAM——索引順序訪問方法)是Indexed Sequential Access Method(索引順序存取方法)的縮寫
它是一種索引機制,用於高效訪問文件中的數據行,擅長與處理高速讀與寫。
(1)存儲方式:
數據,索引,結構分別存儲於不同的文件中。

create table t4(id int,name varchar(32)) engine myisam charset utf8;

在這裏插入圖片描述
mysiam存儲引擎數據表,每個數據表都有三個文件*.frm(結構文件) *.MYD(數據文件) *.MYI(索引文件)
這三個文件支持物理複製、粘貼操作(直接備份還原)。
(2)數據的存儲順序爲插入順序。

create table t5(
id int primary key auto_increment,
name varchar(32) not null
)engine myisam  charset utf8;
insert into t5 values(2223,'劉備'),(12,'張飛'),(162,'張聊'),(1892,'網飛');

在這裏插入圖片描述
(3)併發性
mysiam的併發性較比innodb要稍遜色(mysiam不支持事務)
因爲數據表是“表鎖”
myisam和innodb的取捨
如果表對事務的要求不高,同時是以查詢和添加爲主,我們考慮使用MyISAM存儲引擎,比如bbs中的發帖表,回覆表。
INNODB存儲引擎:
對事務要求高,保存的數據都是重要數據,我們建議使用INNODB,比如訂單表,庫存表,商品表,賬號表等等。
購買成功了庫存 -1,
產生訂單,操作表

4、memory

內存存儲引擎,
特點:內部數據運行速度非常快,臨時存儲一些信息
缺點:服務器如果斷電,重啓,就會清空該存儲引擎的全部數據

create table t6(id int,name varchar(32)) engine memory charset utf8;
insert into t5 values(2223,'劉備'),(12,'張飛'),(162,'張聊'),(1892,'網飛');

mysql服務,重啓後,數據丟失(很不安全,在nosql出現後這個存儲引擎就沒有使用價值)。
在這裏插入圖片描述
關閉數據庫服務再重啓,數據丟失
在這裏插入圖片描述

三、查找需要優化語句

1、慢查詢日誌

是一種mysql提供的日誌,記錄所有執行時間超過某個時間界限的sql的語句。這個時間界限,我們可以指定。在mysql中默認沒有開啓慢查詢,即使開啓了,只會記錄執行的sql語句超過10秒的語句。

方式一、臨時啓動慢查詢記錄日誌

(1){mysql程序所在的目錄}>bin>mysqld.exe --safe-mode --slow-query-log
注意:先把mysql關閉後,再執行以上指令啓動。

在這裏插入圖片描述
進入cmd開始啓動;

>bin>mysqld.exe   --safe-mode  --slow-query-log

在這裏插入圖片描述
通過慢查詢日誌定位執行效率較低的SQL語句。慢查詢日誌記錄了所有執行時間超過long_query_time所設置的SQL語句。
(2)在默認情況下,慢查詢日誌是存儲到data目錄下面的。根據配置文件裏面的配置,找到data的存儲路徑。
在這裏插入圖片描述
(3)可以通過命令查看慢查詢日誌的時間

show variables like 'long_query_time';

修改慢查詢日誌時間:

set  long_query_time=0.001;

在這裏插入圖片描述
(4)測試查詢:
查看慢查詢日誌
benchmark(count,expr)函數可以測試執行count次expr操作需要的時間。

select benchmark(10000,90000000*4);

在這裏插入圖片描述
在這裏插入圖片描述
慢查詢日誌可以記錄查詢數據表較慢的sql語句
(5)一般情況下,一個sql語句執行比較慢,原因是沒有索引
添加索引之前,索引文件大小如下;
沒有添加索引之前查詢時間如下:
在這裏插入圖片描述
添加索引之後:

alter  table  ap_count add index(ip);

在這裏插入圖片描述
另外在MyISAM存儲引擎表中,添加索引後,*.MYI(索引文件)變大,但添加索引會明顯的提高查詢速度。。

方式二:通過修改配置文件,添加如下語句

在配置文件中指定:(1)開啓(2)時間界限

log-slow-queries=‘e:/slow.log’
慢查詢日誌文件存儲的路徑,當前是把慢查詢日誌存儲到d:盤下面,文件名爲slow-log long_query_time=1
指定慢查詢的時間,默認是10秒,我們自定義成1或0.05秒,也就是說當一個sql語句的執行速度超過1秒時,會把該語句添加到慢查詢日誌裏面,

通過修改配置文件是永遠的開啓慢查詢日誌
在這裏插入圖片描述

2、精確記錄查詢時間

使用mysql提供profile機制完成。
profile記錄每次執行的sql語句的具體時間,精確時間到小數點8位

(1)開啓profile機制:

set profiling = 1;

在這裏插入圖片描述
執行需要分析的sql語句(自動記錄該sql的時間)
(2)查看記錄sql語句的執行時間:

show profiles;

在這裏插入圖片描述
注意:不需要分析時,最好將其關閉。

set profiling=0;

四、索引講解

1、索引的基本介紹

利用關鍵字,就是記錄的部分數據(某個字段,某些字段,某個字段的一部分),建立與記錄位置的對應關係,就是索引。
索引的作用:是用於快速定位實際數據位置的一種機制。

例如:
字典的 檢索
寫字樓 導航

索引在mysql中,是獨立於數據的一種特殊的數據結構。
索引一定有順序(排好序的快速查找結構),記錄則不一定。
畫圖說明
在這裏插入圖片描述
測試添加索引前後,對比執行時間。

2、索引的類型:

4種類型:
主鍵索引,唯一索引,普通索引,全文索引。

無論任何類型,都是通過建立關鍵字與位置的對應的關係來實現的。
以上類型的差異,是對關鍵字的要求不同。
關鍵字:記錄的部分數據(某個字段,某些字段,某個字段的一部分)

普通索引:對關鍵字沒有要求。
唯一索引:要求關鍵字不能重複,同時增加唯一約束。
主鍵索引:要求關鍵字不能重複,也不能爲NULL。同時增加主鍵約束。
全文索引:關鍵字的來源不是所有字段的數據,而是從字段中提取的特別關鍵詞。

關鍵詞的來源:可以是某個字段,也可以是某些字段(複合索引)。如果一個索引通過在多個字段上提取的關鍵字,稱之爲複合索引。
比如(複合索引):

alter table emp add   index (field1,field2)

3、索引管理語法

(1)創建索引:
建表時:
注意:索引可以起名字,但是主索引不能起名字,因爲一個表僅僅可以有一個主鍵索引,其他索引可以出現多個。名字可以省略,mysql會默認生成,通常使用字段名來充當。

show create table index1;

在這裏插入圖片描述
更新表結構

alter table index2 add unique key (name),add index(age),add fulltext index(intro),add index(name,age);

在這裏插入圖片描述
注意:
第一點:如果表中存在數據,數據符合唯一或主鍵約束纔可能創建成功。
第二點:auto_increment屬性,依賴於一個KEY(主鍵或唯一)。

(2)刪除索引
修改表結構時完成:
刪除主鍵索引:

alter table  table_name drop primary key;

主鍵索引的刪除,如果沒有auto_increment 屬性則使用 alter table 表名 drop primary key
如果在刪除主鍵索引時,該字段中有auto_increment則先去掉該屬性再刪除。
去除主鍵的auto_inrement屬性:

alter table 表名 modify id int unsigned not null comment '主鍵'

如有主鍵中有auto_incrments屬性時,刪除主鍵索引,則報如圖提示。
在這裏插入圖片描述
去除主鍵的auto_inrement屬性:

alter table index1 modify id int unsigned;

在這裏插入圖片描述
刪除普通索引,唯一索引,全文索引,複合索引;
語法:

alter table 表名  drop index 索引的名稱;

在這裏插入圖片描述
如果沒有指定索引名,則可以通過查看索引的方法得到索引名(一般依賴於索引字段的名字)
(3)查看索引

show indexes from table_name;
show index from table_name\G;
show create table table_name;
show keys from table_name;
desc table_name;

在這裏插入圖片描述

(4)創建索引注意事項(重點):

第一:較頻繁的作爲查詢條件字段應該創建索引
select * from emp where empno = 1
第二:唯一性太差的字段不適合單獨創建索引,即使頻繁作爲查詢條件
select * from emp where sex = '男‘
第三:更新非常頻繁的字段不適合創建索引
select * from emp where logincount = 1
第四:不會出現在WHERE子句中字段不該創建索

五、執行計劃

主要用於分析sql語句的執行情況(並不執行sql語句)得到sql語句是否使用了索引,使用了哪些索引。
語法:

explain  sql語句\G   或 desc sql語句\G 

在這裏插入圖片描述
在這裏插入圖片描述
添加索引進行查看
在這裏插入圖片描述
刪除索引時,在看執行計劃
在這裏插入圖片描述

六、索引的數據結構

查看索引的類型:

show keys from 表名;

在這裏插入圖片描述
在這裏插入圖片描述

1、myisam的存儲引擎索引結構:

索引的節點中存儲的是數據的物理地址(磁道和扇區)
在查找數據時,查找到索引後,根據索引節點中記錄的物理地址,查找到具體的數據內容。

在這裏插入圖片描述

2、innodb的存儲引擎的索引結構

innodb的主鍵索引文件上 直接存放該行數據,稱爲聚簇索引,非主索引指向對主鍵的引用(非主鍵索引的節點存儲是主鍵的id)
在這裏插入圖片描述
比如要通過nam創建的索引,查詢name=’採臣’的,先根據name建立的索引,找出該條記錄的主鍵id,再根據主鍵的id通過主鍵索引找出該條記錄。

innodb的主索引文件上 直接存放該行數據,稱爲聚簇索引,非主索引指向對主鍵的引用
myisam中, 主索引和非主索引,都指向物理行(磁盤位置).
注意: innodb來說,

1: 主鍵索引 既存儲索引值,又在葉子中存儲行的數據
2: 如果沒有主鍵, 則會Unique key做主鍵
3: 如果沒有unique,則系統生成一個內部的rowid做主鍵.
4: 像innodb中,主鍵的索引結構中,既存儲了主鍵值,又存儲了行數據,這種結構稱爲”聚簇索引”

聚簇索引

優勢: 根據主鍵查詢條目比較少時,不用回行(數據就在主鍵節點下)
劣勢: 如果碰到不規則數據插入時,造成頻繁的頁分裂(索引的節點移動).

七、索引覆蓋

索引覆蓋是指:如果查詢的列恰好是索引的一部分,那麼查詢只需要在索引區上進行,不需要到數據區再找數據,這種查詢速度非常快,稱爲“索引覆蓋”
索引覆蓋就是,我要在書裏 查找一個內容,由於目錄寫的很詳細,我在目錄中就獲取到了,不需要再翻到該頁查看。
先分析一下使用場景,爲什麼使用索引覆蓋,有什麼好處?
準備兩張表來測試使用;
在這裏插入圖片描述

案例1,比如給id建立了主鍵索引,使用id查詢數據。
在這裏插入圖片描述

在nav_middle_level表裏面,給middle_name字段添加索引,查詢middle_name,就用到了索引覆蓋。
在這裏插入圖片描述
索引使用的場合如下,在沒有條件時,直接查詢建立索引的字段時,

案例2:比如給id和name 建立了複合索引,使用middle_name作爲條件查詢。
沒有創建索引時,

給id和middle_name創建複合索引。
在這裏插入圖片描述
典型情況如下:
學生表:
共30個字段。

Select id, name, height,gender from student where name=’XXX’;

建立索引:

Alter table student add index (name);
Alter table student add index (name, id, height, gender, class_id);
select name, id, height, gender, class_id from student

負面影響,增加了索引的尺寸。
保證該索引的使用率儘可能高,索引覆蓋纔有意義。

八、索引的使用原則

1、列獨立

只有參與條件表達式的字段獨立在關係運算符的一側,該字段纔可能使用到索引。
“獨立的列”是指索引列不能是表達式的一部分,也不能是函數的參數。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2、like查詢

在使用like(模糊匹配)的時候,在左邊沒有通配符的情況下,纔可以使用索引。
在mysql裏,以%開頭的like查詢,用不到索引。
在這裏插入圖片描述
注意,如果select的字段正好就是索引,那麼會用到索引即索引覆蓋。
在這裏插入圖片描述
如果該表改爲innodb引擎,因爲非主鍵索引中存儲的是id,select的字段是id因此用到了索引覆蓋。
比如如下把表改成了 innodb的引擎,對name建立了索引,如下查詢,就用到了索引覆蓋。
改存儲引擎語法:

alert table 數據表名稱 engine=存儲引擎類型(innodb/myisam)

在這裏插入圖片描述
如果是innodb的表,可以如上使用。
在這裏插入圖片描述
注意以下查詢會用到索引;
在這裏插入圖片描述

3、OR運算都具有索引

如果出現OR(或者)運算,要求所有參與運算的字段都存在索引,纔會使用到索引。

如下:middle_name有索引,high_id沒有索引
在這裏插入圖片描述
如下:id有索引,name有索引

在這裏插入圖片描述

4、複合索引使用

當前查詢環境已有索引;
先刪除和添加索引
在這裏插入圖片描述
在這裏插入圖片描述
**最左原則:
對於創建的多列(複合)索引,只要查詢條件使用了最左邊的列,索引一般就會被使用。
**
在這裏插入圖片描述
注意:在多列索引裏面,如果有多個查詢條件,要想查詢效率比較高,比如如下建立的索引,
index(a,b,c,d) 要保證最左邊的列用到索引。

4、mysql 智能選擇

如果mysql認爲,全表掃描不會慢於使用索引,則mysql會選擇放棄索引,直接使用全表掃描。一般當取出的數據量超過表中數據的20%,優化器就不會使用索引,而是全表掃描。
在這裏插入圖片描述

5、優化group by語句。

默認情況下, mysql對所有的group by col1,col2進行排序。這與在查詢中指定order by col1,col2類型,如果查詢中包括group by 但用戶想要避免排序結果的消耗,則可以使用order by null禁止排序。

輸出班級的id,high_id
在這裏插入圖片描述
根據high_id分組,自動根據high_id進行 了排序,

select high_id,sum(id) from nav_middle_level group by high_id;

在這裏插入圖片描述
如果不想根據high_id排序,則可以在後面使用order by nulll

select high_id,sum(id) from nav_middle_level group by high_id order by null;

通過分析語句發現:
在這裏插入圖片描述

九、mysql中鎖機制

1、應用場合:

比如有如下操作:

(1)從數據庫中取出id的值(比如id=100)
(2)把這個值-1(id=100-1)
(3)再把該值存回到數據庫(id=99)

假如id=1
有兩個進程(用戶)同時操作,
使用鎖機制來完成,
同時操作時,只有一個進程獲得鎖,其他進程就等待,
進程1
添加鎖
id =100
id=100-1
id=99
釋放鎖
進程2
wating等待
wating等待
wating等待
id =100
id=100-1
id=99

2、mysql裏面的鎖的幾種形式

鎖機制:
當客戶端操作表(記錄)時,爲了保證操作的隔離性(多個客戶端操作不能相互影響),通過加鎖來處理。
操作方面:
讀鎖:讀操作時增加的鎖,也叫共享鎖,S-lock。特徵是所有人都只可以讀,只有釋放鎖之後纔可以寫。
寫鎖:寫操作時增加的鎖,也叫獨佔鎖或排他鎖,X-lock。特徵,只有鎖表的客戶可以操作(讀寫)這個表,其他客戶讀都不能讀。
辦公室開會鎖上門。
鎖定粒度(範圍)
表級鎖:開銷小,加鎖快,發生鎖衝突的概率最高,併發度最低。
myisam引擎的表支持表鎖,
行級鎖:開銷大,加鎖慢,發生鎖衝突的概率最低,併發度也最高。
innodb引擎的表支持行鎖與表鎖。

3、表鎖的演示,

建立測試表,並添加測試數據:
create table user(
id int primary key auto_increment,
name varchar(32) not null default ‘’,
age tinyint unsigned not null default 0,
email varchar(32) not null default ‘’,
classid int not null default 1
)engine myisam charset utf8;
insert into user values(null,‘xiaogang’,12,‘[email protected]’,4),
(null,‘xiaohong’,13,‘[email protected]’,2),
(null,‘xiaolong’,31,‘[email protected]’,2),
(null,‘xiaofeng’,22,‘[email protected]’,3),
(null,‘xiaogui’,42,‘[email protected]’,3);

添加鎖的語法:

lock table table_name1 read|write,table_name2 read|write;

釋放鎖的語法:

unlock tables;

(1)添加讀鎖
語法:

lock  table_name   read|write;

在這裏插入圖片描述
另外一個用戶登錄後,不能執行修改操作,可以執行查詢操作。

在這裏插入圖片描述
注意:添加讀鎖後,自己和其他的進程(用戶)只能對該表查詢操作,自己也不能執行修改操作。
釋放鎖之後,另外的一個進程,可以執行修改的操作了。

在這裏插入圖片描述
查看另外的一個用戶,是否可以操作該表,其他的用戶,讀都不能讀,處於阻塞狀態

在這裏插入圖片描述

4、行鎖的演示

innodb存儲引擎是通過給索引上的索引項加鎖來實現的,這就意味着:只有通過索引條件(主鍵)檢索數據,innodb纔會使用行級鎖,否則,innodb使用表鎖。
先改變存儲引擎

alter table user engine innodb;

在這裏插入圖片描述
語法:

begin;

執行語句;

commit; 

當前用戶添加行鎖,
另外的一個用戶登錄,進行操作。
在這裏插入圖片描述

5、通過php代碼來實現鎖機制。

在apache裏面有一個bin目錄 下面有一個ab.exe工具,該工具可以模擬多個併發測試。
在這裏插入圖片描述
語法:

ab.exe  –n 總的請求數  -c 併發數  url地址;

具體的一個步驟:
(1)創建一個表,表裏面就只有一個字段,便於我們演示。

create table t7(id int)engine myisam charset utf8;
insert into t7 values(100);
select * from t7;

在這裏插入圖片描述
(2)通過代碼來完成,
從數據庫中取出id的值(比如id=100)
把這個值+1(id=100+1)
再把該值存回到數據庫(id=101)

D:\phpStudy\WWW建立個php文件
demo.php

<?php
$pdo  = new PDO('mysql:host=localhost;dbname=app1','root','root');
$pdo->exec('set names utf8');
//取出id的值
$res = $pdo->query('select id from t7');
$info = $res->fetch(PDO::FETCH_ASSOC);
$id = $info['id'];
//給id的值加1操作
$id = $id+1;
//把該值再寫入;
$pdo->exec("update t7 set id=$id");
echo 'ok';
?>

(3)使用ab工具模擬併發操作。
在這裏插入圖片描述
查看錶裏面的id的值,我們執行了代碼50次,應該id的值是150纔對(性能差則低於150),則說明我們請求的50個併發,有幾個併發是同時執行的。
在這裏插入圖片描述
demo.php把註釋去掉,添加鎖機制。

<?php
$pdo  = new PDO('mysql:host=localhost;dbname=app1','root','root');
$pdo->exec('set names utf8');
//添加鎖
$pdo->exec('lock table t7 write');
//取出id的值
$res = $pdo->query('select id from t7');
$info = $res->fetch(PDO::FETCH_ASSOC);
$id = $info['id'];
//給id的值加1操作
$id = $id+1;
//把該值再寫入;
$pdo->exec("update t7 set id=$id");
$pdo->exec('unlock tables');//是否鎖
echo 'ok';
?>

加鎖後會有一定的阻塞
在這裏插入圖片描述
使用mysql裏面鎖機制缺點:就是阻塞,假如有一張goods表,goods表裏面有一個庫存的字段,當前下訂單時,如果鎖定了goods表,還能執行查詢goods表嗎?
會阻塞拖慢整個網站的速度,一但鎖定goods表(添加寫鎖,要更改庫存),則其他進程就無法查詢goods表。
可以使用文件鎖,
demo.php

<?php
$pdo  = new PDO('mysql:host=localhost;dbname=app1','root','root');
$pdo->exec('set names utf8');
//添加文件鎖
//$pdo->exec('lock table t7 write');
$fh = fopen('./lock.txt','w');
flock($fh,LOCK_EX);
//取出id的值
$res = $pdo->query('select id from t7');
$info = $res->fetch(PDO::FETCH_ASSOC);
$id = $info['id'];
//給id的值加1操作
$id = $id+1;
//把該值再寫入;
$pdo->exec("update t7 set id=$id");
//$pdo->exec('unlock tables');//是否鎖
flock($fh,LOCK_UN);
echo 'ok';
?>

在這裏插入圖片描述
開始執行50個併發,測試效果如下;
在這裏插入圖片描述

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