MySQL基礎、主從復制、優化


MySQL

apache公司 開源共享 免費

mysql [-hlocalhost] -uroot -p 以超級管理員的身份登錄

use demo; 查看

  • DCL(數據庫控制語言):

  • DDL(數據庫定義語言):

  • DML(數據庫操縱語言):

  • DQL(數據庫查詢語言):

  • TCL(事務控制語言):

  • 數據庫鎖:

  • 主從配置:

命令行鏈接方式
mysql -u用戶名   -p密碼  -h服務器IP地址   -P服務器端口MySQL端口號   -D數據庫名
mysql -uroot -p9264934.. -hlocalhost -P3306 -Dguanli

數據庫控制語言命令(DCL):

創建本地用戶

-- 選擇mysql數據庫
use mysql;
-- 創建本地用戶
create user 'superboy'@'localhost' identified by 'iamsuperboy';
-- 刷新MySQL的系統權限相關表,使添加用戶操作生效,以免會出現拒絕訪問
flush privileges;
創建遠程用戶

-- 從192.168.122.12登陸的用戶
create user 'superboy'@'192.168.122.12' identified by 'password';
-- 從任意ip登陸的用戶
create user 'superboy'@'%' identified by 'password';
-- 不做指定默認為'%'
create user 'superboy' identified by 'password';

對用戶的基本操作


創建用戶
create user 'wang'@'localhost' identified by 'iamsuperboy';

修改用戶的權限:
grant all privileges on *.* to 'wang'@'%';

# all 可以替換為 select,delete,update,create,drop
-- 賦予部分權限,其中的shopping.*表示對以shopping所有文件操作。
grant select,delete,update,insert on 數據庫.* to 'wang'@'localhost' identified by
'superboy';

-- 賦予所有權限
grant all privileges on 數據庫.* to superboy@localhost identified by 'iamsuperboy';

'revoke'
--撤銷權限
revoke privlieges_type on 權限名 from 用戶名

刪除用戶:
Delete FROM mysql.user Where user='user_name' and host='localhost' ;

--允許遠程鏈接
grant all privileges on *.* to 'root'@'%' identified by 'mysql' with grant option;flush privileges;--刷新
修改密碼
1、set password for 'wang'@localhost = '123456'
2、update mysql.user set password=password('新密碼') where user='root' and     host='localhost' flush privileges;
3、mysqladmin -u用戶名 -p舊密碼 password 新密碼

#忘記root密碼
1、停掉mysql服務 serve mysql stop
2、cmd中進入安裝目錄bin 然后 mysqld --console --skip-grant-tables --shared-memory  #跳過權限檢查
3、再開啟另一個cmd進入mysql    #直接輸入mysql
4、flush privileges
5、退出,並重啟系統

 

數據庫備份

mysqldump -u [username] -p[password] [database_name] > [文件夾路徑]
mysqldump -uroot -p9264934.. -hlocalhost wangwei > mysql


mysqldump -u [username] -p[password] --no-data [database_name] > [文件夾路徑] #只要結構,不要數據
mysqldump -uroot -p9264934.. -hlocalhost --no-data wangwei > mysql


mysqldump -u [username] -p[password] --no-create-info [database_name] > [文件夾路徑] #只要數據,不要結構
mysqldump -uroot -p9264934.. -hlocalhost --no-create-info wangwei > mysql


mysqldump -u [username] -p[password] [dbname1,dbname2] > [文件路徑]  #備份多個數據庫

 

 

數據庫查詢
  • 數據庫查看


- 查看所有的表:show tables

- 查看表的信息: show  full tables;

- 查看相關列:show columns from teach;
show columns from teach like 'id';
show columns from teach like '%e%'; #查看帶有 ’e‘的內容
  • 查看用戶信息


查看當前用戶:select user();
select current_user();

查看當前有多少用戶登錄
select user,host,db,command from information_schema.procrsslist:

 

數據庫維護
  • 分析表

analyze table 表名1 [表名2]
  • 優化表

optimize table 表名
  • 檢查表

check table 表名
  • 修復表

repair table 表名

 

 

  • 查看表的字段內容


desc t1;         //自增 primary key//主鍵
  • 添加數據


insert into t1 values(1,'tom','man',18);

insert into t1 (id,name,sex,age) values(1,'tom','man',18);
  • sql注入


" or 1=1;--

 

  • 查看數據是否添加成功


select * from t1;
  • 刪除一個表


drop t1;
  • 刪除表中的一行數據


delete from stu where id=1
  • 替換某字段內容的update語句


update t1 set id=replace(id,1,2);

update t1 set sex='woman' where c_id=1;

 

數據庫定義語言(DDL)

新建數據庫

create database [if not exists] database_name
刪除數據庫

drop database [if exists] database_name
創建表

create table ceshi1(
id int(10) not null auto_increment primary key,
name varchar(10),
age varchar(10),
sex enum('男','女') NOT NULL,
phone varchar(11) unique,
habbit set("游泳","健身"),
pasword varchar(32))default charset=utf8;    comment='示例';

 

修改表

alter table 表名 add|drop|modify|change|alter|rename

  • alter 增加列


alter table user add sex enum("男","女") not null [after name]
  • alter 增加在table最后一列 的一個屬性


alter table t2 add hobby char(20);
  • alter 在table的第一列添加新字段屬性


alter table t2 add project int first;
  • alter 在sex字段之后添加新字段num屬性


alter table t2 add num int after sex;
  • alter 刪除表中的字段


alter table t2 drop class_id; //刪除class_id字段
  • alter 添加主鍵


alert table t2 primary key(id)
  • alter (設置默認值)


ALTER TABLE student ALTER class_id SET DEFAULT 0;//設置默認值為0
ALTER TABLE student ALTER class_id DROP DEFAULT;//刪除默認值

*為什么有了MODIFY和CHANGE還要來個ALTER呢?這是因為另外兩個在修改的時候會把字段之前舊的屬性全部覆蓋掉

舉個例子:現在需要修改class_id DEFAULT的值,我們需要這么寫

ALTER TABLE student MODIFY class_id VARCHAR(20) DEFAULT 10;


而采用ALTER則不需要則可以只需要設置默認值

 

  • modify && change (修改字段)

區別:change必須指定新的字段名而modify則不需要

如果需要修改字段名只能用CHANGE,否則用哪個都可以


alter table t1 modify num char(10);
//modify 修改num 的數據類型int(10)=>char(10)

 


ALTER TABLE t2 CHANGE class_id c_id VARCHAR(20);
//將class_id字段名改為c_id並修改數據類型為VARCHAR(20)
ALTER TABLE t2 CHANGE class_id class_id VARCHAR(20);
//修改class_id數據類型為VARCHAR(20)不修改字段名
ALTER TABLE t2 MODIFY class_id VARCHAR(20);
//將class_id數據類型修改為VARCHAR(20)

 

  • rename (重命名數據表)

alter table t2 rename to t2s;
修改存儲引擎
  • 修改引擎


#先刪除再添加
alter table t2s engine=myisam;   //將存儲引擎修改為myisam
  • 刪除引擎


alter table t2 drop index column_name
  • 刪除引擎


alter table t2 engine=InnDB
show engines
show create table 表名
  • 修改自增值(開始值)


alter table t2 auto_increment = 1

 

MyISAM

不支持事務,不支持外鍵,訪問速度特別快(主要的基本應用為insert,select),創建成功后,有以下三個文件,擴展名分別為(二進制)

  • .frm(存儲表定義,表結構)

  • MYD(MYData存儲數據)

  • MYI(MYIndex,存儲索引)

InnoDB
  • 健壯的事務型存儲引擎

  • 更新密集的表

  • 自動災難恢復

  • 外鍵約束

  • 需要事務支持

 

索引類型
  • 主鍵索引 primary

    • 一個表中唯一的,在數據的查詢,寫入,讀出能夠按照一定的順序,一定排列進行有序的操作,並且除主鍵外的其他的字段都會收到其影響

    • 主鍵的值只能是唯一的,不能重復,auto_increment

  • 唯一的鍵 unique

    • 一個表中能夠給多個字段設置唯一的鍵,他會在查詢本字段,形成一定的順序,分組查詢

    • 在本字段中,不能出現相同的內容,除了NULL外

  • 普通索引 index

    • 能給多個字段設置普通索引,會在查詢本字段

  • 文本索引 fulltext mysql 5.7版本后有效

    • 文本編輯器

    • 幫助我們在大批文本中有序查找內容

 

外鍵
  • 查看外鍵


show create table student;

 

  • 創建外鍵


alter table student
add foreign key(cid)
references classes(cid) on delete cascade;
  • 刪除外鍵


alter table student
drop key aa;  #刪除約束
alter table student
drop foreign key aa;   #刪除鍵

 


1、create table if not exists classes(     #創建主表 :班級表
cid int(10) auto_increment primary key,
cnaem varchar(20))default charset=utf8


2、create table if not exists student(     #創建副表 :學生表
sid int(10) auto_increment primary key,
snaem varchar(20),
cid int(10),
constraint aa foreign key(cid) references classes(cid) # ******加外鍵
)default charset=utf8
  • 外鍵鏈接下,刪除主表內容提示


on delete
district(默認)     cascade(同時刪除)   no action(什么都不做)   set null(設置為空)

on update
district(默認)     cascade(同時刪除)   no action(什么都不做)   set null(設置為空)


create table if not exists student(     #沒附表的情況下   創建副表
sid int(10) auto_increment primary key,
snaem varchar(20),
cid int(10),
constraint aa foreign key(cid) references classes(cid) on delete cascade
)default charset=utf8

#或

alter table student     #有副表沒外鍵的情況下
add foreign key(cid)
references classes(cid) on delete cascade;

 

數據庫操縱語言(DML)

insert
  • 插入的內容與原unique的id等唯一值沖突的時候


insert into student (sid,sname,cid) values (3,ai,3) on duplicate key update sid=sid+1     #student 內有sid=3的數據
  • 快速復制一個表的結構


create table aaa like stu
  • 快速復制一個表的內容


insert into aaa select * from stu

 

 

  • replace

可以置換現有的主鍵或unique


replace into aaa (sname, cid) value("zhangsan",3)

 

update

update low_priority t1 #low_priority 延遲更新,等沒人查詢在更新 set column_name1 = expr1 column_name2 = expr2


where
condition
show full tables
  • 帶有select子句的更新


update stu set sname='111' where id=5;
select tname from teach order by id asc;#隨機取 desc倒序
select tname from teach order by rand() limit 1;
#兩個表之間的更新
update stu set tname=(select tname from teach order by rand() limit 1) where tname is null;
#關聯更新
update table1,table2,...
set table1.attr=val,table2.attr=val,...
where condition

update table1 join table2 on...
set table1.attr=val,table2.attr=val,...
where condition

 


update classes,student where classes.cname=student.sname set classes.cname="aa",student.sname=""  

 

delete
  • 帶有limit的刪除語句


delete from student order by id desc limit 1  #刪除id從后致前的第一個

 

  • 關聯刪除


delete classes,student from classes,student where classes.cname="allj"

 

 

清空數據

delete fro student     # 逐條刪除,主鍵自增不會從1開始,而是繼續,效率低

truncate [table] student     #自增從1開始 效率高

 

日志管理

記錄服務器運行信息,通過日志文件可以監視服務器的運行狀態和性能,還能對服務器進行排錯與故障處理

  • MySQL有六種不同類型的日志:

    • 錯誤日志:記錄啟動,運行或停止時出現的問題,一般也記錄警告信息 一般開啟

    • 一般查詢日志:記錄客戶端的鏈接和執行的語句 一般關閉

    • 慢查詢日志:記錄所有執行時間超過long_time的所有不適用索引的

    • 二進制日志:數據庫信息有任何改變,都會放到二進制日志中 (需要指定)

    • 中繼日志:

    • 事務日志:

  • 查詢變量


    show global variables [like '%log%']
  • 修改變量


    set global variables_name=val  
  1. 錯誤日志

    1. 查看錯誤日志地址


      show global variables like ”log_error"    
    2. 警告信息開關


      show global variables like "log_warnings"; #查看是否開啟 開啟為1,關閉為0
      set global log_warnings=0   #關閉
  2. 一般查詢日志


    1. 啟用開關:general_log=(ON|OFF)     #set global general_log=ON   一般時候都關閉
    2. 記錄類型:log_output #show global variables like
    3. 查看存儲位置:general_log_file       #show global variables like
    1. 查看錯誤日志地址


      show global variables like ”log_error"   警告信息開關2.

      2.錯誤警告開關


    show global variables like "log_warnings"; #查看是否開啟 開啟為1,關閉為0
    set global log_warnings=0   #關閉
  3. 慢查詢日志

    放到配置文件中


    查詢超時時間: long_query_time=3
    查詢慢查詢 : log_slow_querys={YES|NO}
    啟動慢查日志: log_query_log=1 (on|off)
    日志記錄文件: slow_query_log_file[=file_name]

數據庫查詢語言(DQL)

* 通配符 所有

函數 描述
escape ‘$’ 把 $ 規定為轉義字符
cast(1982-3-1 as data) 把1928-3-1轉換成data型
count(cname) cname的條數
sqlfind_in_set(needle,place) needle:查詢內容 place:所在字段
select

select count(cname) as num from classes

 


select

column_1 , column_2,...

from a

table_1
  • 模糊查詢

    內容 描述
    %老師 以老師結尾的數據
    老師% 以老師開頭的數據
    _老師 老師前面只有一個可變量
    老師_ 老師后面只有一個可變量
    like 精確查詢
    = 精確查詢
  • where
  • 語句順序


where

conditions

group by column_1

having group_conditions

order by column_

limit offset, length

操作符                                   描述
=                    #等於,幾乎任何數據類型都可以用
<> !=                #不等於
<
>
<=
>=

邏輯運算符
or                   #或者
and                  #並且
not #非
操作/邏輯運算符 描述
= 等於
<>!= 不等於
< 小於
> 大於
<=  
>=  
or
not
and
  • between 包含兩端

    (cast(1982-3-1 as data) 把1928-3-1轉換成data型)


 select * from student where birth between cast(1982-3-1 as data) and cast(1988-6-10 as data) ;
  • in


select * from classes where sqlfind_in_set(l,cname)   #一個字段中含多個內容

 

 

  • group by

select
c1,c2,c3,....
from
table
where
where_conditions
group by t1,t2,t3...;

 

having

分組后進行篩選 where是分組前篩選

having后可跟條件(函數)

 

函數 描述
avg() 計算一組值
count()  
instr()  
sum()  
min()  
max()  

1、通過時間分類 看一時間段內進貨 額

2、通過類別

3、時間、類

 

  • order by

單列或多列查詢結果 進行升序或降序排序


select column1,column2,...
from t2
order by num desc,price asc  #降序排列   asc升序   以前一列為基礎,再排后一列

select column1,column2,...
from t2
order by field(name,"商品3","商品2","商品1")desc / asc    #自定義排序

 

  • limit

約束查詢結果的行數 ,一般跟order by 一起使用


select column1,column2,...
from tablename
limit offset , count     #offset:偏移量     count:條數
#只有一個參數n:從頭開始取n條

select * from goods where cid=1 group by cid desc limit

 

 

關聯查詢

表與表之間有關系,通過關系去查詢

MySQL支持一下連接:

  • 交叉鏈接


select cname,gname
from category cross join goods;

 

  • 內鏈接


select
name
from
t1
inner join
t2 on t1.id=t2.id

 

  • 左連接


select              #以左面為基礎
name
from
t1
left join
t2 on t1.id=t2.id

 

  • 右連接


select              #以右面為基礎
name
from
t1
right join
t2 on t1.id=t2.id
  • 聯合查詢


union    #可以去掉重復項   union all 包括重復項

select cname from category union select gname from goods;

 

子查詢

把一個查詢嵌套在另一個查詢,叫內部查詢

  • 分類

    1. 標量子查詢:返回但一直的標量,最簡單的形式

    2. 列子查詢:返回結果是N行一列

    3. 行子查詢:返回結果為一行N列

    4. 表子查詢:返回結果為N行N列

 

  1. 標量子查詢(一個值)


select * from article where uid = (select uid from user where status=1 order by uid desc limit 1)                  in    
  • 關鍵字 any all

    any :< > = <>條件中的任何一個就可以

    all: < > = <> 條件中的所有條件才可以


    select * from goods where cid < any (select id from category where id=3 or id=2)
                                  #all

2.列子查詢


 

函數

聚合函數

總值,平均值,最大值,最小值,求和 除count外會忽略null

  • count()


    select count(*) from category group by cid;
  • avg 平均數


  • num

  • max(),min()

  • group_conatan()

    把分組后的結果連接起來


    select group_concat(gname) from goods group by cid;  
  • concat() 字符串鏈接函數


    select concat("first","last") from names

    #concat_wg()   指定連接符號
    select concat_ws("-","first","last") from names

 

  • left() 指定從左至右取的內容長度


 select left ("abcdef",3)
 "abc"

 

  • replace() 替換,更新


 select replace("this is firts","firts","first")  #把""中的 firts 換成first

 

  • substring() 截取 可以從任意位置取


 select substring("abcdefg"2,2)   #從第二位開始,取兩個

 

  • trim() 刪除不必要的前導或尾隨字符


 select trim({both|leading|trailing} from str)
 
 select trim("   abcd   ")  #默認去掉前后的空格
 select trim(leading from    "abcd"   )  #之去掉前面的
 select trim(leading "a" from    "abcd"   )  #去掉前面的 a
 select trim(both "a" from    "abcd"   )   #去掉所有的 a

 

 

  • format 保留有效數字位數

    默認en_US


 select format(1001.353535,2)   #保留三位
 select format(1001.353535,2,"de_DE")   #默認en_US 改成 de_DE

 

時間函數
  • curdate() 返回當前的日期


select curdate()
  • now()


select now()
select now(),sleep(5),now()
  • sysdate()

    返回指定日期函數


select sysdate()
select sysdate(),sleep(5),sysdate()
  • day() 獲取今天幾號

  • month()


select month(now());
  • year()

  • weekday(now()) 獲取星期幾

  • dayname() 獲取星期幾英文名稱


set @@lc_time_names = 'zh_CN';     #改中文
select dayname(time) from goods;

 

時間計算函數
  • datediff()


select datediff("2017-08-03","2018-08-03")   #相差幾天

 

  • timediff()


select timediff("2017-08-03 12:00:00","2018-08-03 12:00:00")    #相差得時間  

 

  • timestampdiff( unit, begin,end)

    unit:microsecond second minute hour day week month quarter year


#unit:microsecond,second,minute,hour,day,week,month,quarter,year
select timestampdiff(day,"2017-08-03 12:00:00","2018-08-03 12:00:00")    #相差得時間用什 么單位表示  

 

  • date_add(start_date,interval expr unit)

    在開始時間上加一個時間后得到的時間


select date_add("2018-12-31 23:59:59",interval "1:1" minute_second)

 

視圖

mysql中有一些復雜的語句,對於復雜的查詢,每一次查詢都是對性能的消耗,而視圖就是把第一次所查詢出來的內容做成一個表

  • 查看所有視圖


show full view
  • 查看視圖創建過程


show create view viewname

 

  • 創建視圖


create view viewname as select ...
  • 修改視圖


alter view viewname as select ...
  • 創建或替換視圖

沒有就創建,有就修改


creat or replace view viewname as select ...     #viewname:視圖名
  • 刪除視圖


drop view [databases.name].[viewname]

 

臨時表

使用頻率低,不想每一次都查詢,又不想創建視圖,臨時保存數據,生命周期為數據庫使用期間,自動刪除

  • 創建


create temporary table tempname select ...   #沒有as   tempname:臨時表表名

 

事務

只有InnoDB支持事務

數據庫處理操作,執行就好像它是一個單一的一組有序的工作單元,在組內每個單獨的操作是成功的,那么一個事務才是完整的,如果事務中任何操作失敗,整個事務將失敗。

事務性質

  • 原子性:確保了工作單位中的所有操作都成功完成:否則,事務被終止,在失敗時會被回滾到事務操作以前的狀態。

  • 一致性:可確保數據庫在正確的更改狀態在一個成功的結果提交事務。

  • 隔離:使事務相互獨立地操作。

  • 持久性:確保了提交事務的結果或系統故障情況下仍然存在作用。

 

事務控制語句

  • BEGIN或START TRANSACTION;顯示地開啟一個事務;

  • COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會提交事務,並使已對數據庫進行的所有修改成為永久性的

  • ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。回滾會結束用戶的事務,並撤銷正在進行的所有未提交的修改

  • SET AUTOCOMMIT=0 禁止自動提交

  • SET AUTOCOMMIT=1 開啟自動提交 variable

 

不同的存儲引擎支持不同的鎖機制 mysql中鎖的大分類分為:1、表級鎖,2、行級鎖,3、頁面鎖

  • 表級鎖:開銷小,加鎖快,不會出現死鎖,鎖定粒度大,發生鎖沖突的概率最高,並發度最低

  • 行級鎖:開銷大,加鎖慢,會出現死鎖,鎖定粒度小,發生鎖沖突的概率低,並發度高。

 

表級鎖

共享鎖:讀鎖,所有人(包括自己)能查看,不能修改(修改會提示錯誤),鎖期間不能操作別的表

獨占鎖:寫鎖,只有 自己可見可修改,鎖期間不能操作別的表

  • mysql表級鎖存儲引擎:

    • MyISAM 引擎

    • MEMORY 引擎

  • 加鎖(用到MySQL時候,MySQL本身已經給加鎖了)

演示事務操作的時候 操作多條命令時,不希望被其他用戶修改


lock tables t1 [t2] read [local],      lock tables t1 [t2] write [local]
  • 釋放鎖


unlock tables;
  • 查看表鎖征用情況:

    • table_locks_immediate

    • table_locks_waited


    show status like "table%"  
    show status like "%lock%"
    show processlist   #查看那些當前是哪些命令在等待,從而進行優化
    show open tables   #當前倍速歐珠的表以及鎖的次數

 

 

  • 表鎖優化
  • optimize table 表名

  • set concurrent_insert=2 允許並發插入

  • 是否設置寫的優先級,(登錄)

  • 是否設置寫內存,解決批量插入數據(新聞系統更新)

  • 解決並發問題

    • 並發插入(只能插入,不能修改和刪除)

      MyISAM存儲引擎有一個系統變量 concurrent_insert ,專門控制並發插入行為 值可為 0,1,2

      1. cuncurrent_insert 為0時:不允許並發插入

      2. cuncurrent_insert 為1:如果MyISAM沒有空洞:即使有鎖,也會從尾部插入 有空洞:不插入 (空洞:id=1,2,4 少3)

      3. cuncurrent_insert 為2:加鎖的時候把 [local] 加上 allways 總是可以隊尾插入信息(鎖的情況下)********很重要,用mysql就改成2 set cuncurrent_insert=2

  • 讀寫鎖的優先級

    • 修改寫鎖的最大次數


    set global max_write_lock_count=1      #寫一次之后暫停寫操作,給讀操作機會
    • 降低寫鎖的優先級


    set global low_priority_updates=1
  • 設置寫內存

    可以根據具體的業務設置讀寫內存


    max_allowed_packet=1M      # 限制接受的數據包大小,大的插入和更新會被簡直掉
    net_buffer_length=2k       #insert 語句的緩存值 (),(),() 2k-16M
    bulk_insert_buffer_size=8M   #一次性insert語句插入的大小

間隙鎖

數據庫里id有 1,3,4,5 鎖是id>1 再操作id=2的時候也會被鎖。所以確定條件的時候一定要有范圍

行級鎖

引擎:InnoDB

如果一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之如果兩者不兼容,該事務就要等待鎖釋放

 

  • 請求鎖是否兼容當前鎖模式

  X(排他鎖) IX(意向排他鎖) S(共享鎖) IS(意向共享鎖)
X 沖突 沖突 沖突 沖突
IX 沖突 兼容 沖突 兼容
S 沖突 沖突 兼容 兼容
IS 沖突 兼容 兼容 兼容
  • 特點

    • 想讓InnoDB 上行鎖,當前行的操作字段必須要有索引。

    • 如果操作行的操作字段沒有索引,行鎖會自動升級為表鎖。

    • 即使有索引,但用字段的時候修改了類型,索引失效 eg:(規定類型:name varchar(255) 命令輸入:name=0;)

    • 意向鎖是InnoDB自己加的,不用干預;對於update,delete和insert,InnoDB會自動加排他鎖(X);對於select不會自動加共享鎖(S)。

    • 當對一行上了排他鎖(update,delete,insert),其他用戶對這一行數據沒有任何權限,但並不影響其他用戶修改其他數據。

    • 當對一行上了排他鎖(update,delete,insert)后,其他用戶可以對當前行進行讀操作:修改前的值(InnoDB默認隔離方式)。

    • 研究行鎖時,需要將自動提交關閉,


      set autocommit = 0
      #注:如果有多個客戶端,每個都要設置
  • 加鎖


    共享鎖:select 后需要加  lock in share mode
    排他鎖:select 后需要加  for update
  • 釋放鎖


    commit;
    rollback;
  • 查詢行鎖征用


show status like 'innodb_row_lock%';
  • 隔離

  • 查看隔離級別


select @@session.tx_isolation
  • 設置隔離級別


set session transaction isolation level read uncommitted(讀未提交)  #臟讀
      #read committed(不可重復度)
      #read (可重復讀)          
#read用到mvcc技術(多版本並發控制)Multiversion Currency control
  • 隔離級別

    • 可讀取未確認(Read uncommitted)

      寫事務阻止其他寫事務,避免了更新遺失。但是沒有阻止其他讀事務。

      存在的問題:臟讀。即讀取到不正確的數據,因為另一個事務可能還沒提交最終數據,這個讀事務就讀取了中途的數據,這個數據可能是不正確的。

      解決辦法就是下面的“可讀取確認”。

    • 可讀取確認(Read committed)

      寫事務會阻止其他讀寫事務。讀事務不會阻止其他任何事務。

      大部分數據庫使用的默認隔離級別,兼顧速度和正確性。

      存在的問題:不可重復讀。即在一次事務之間,進行了兩次讀取,但是結果不一樣,可能第一次id為1的人叫“李三”,第二次讀id為1的人就叫了“李四”。因為讀取操作不會阻止其他事務。

      解決辦法就是下面的“可重復讀”。

    • 可重復讀(Repeatable read)

      讀事務會阻止其他寫事務,但是不會阻止其他讀事務。

      存在的問題:幻讀。可重復讀阻止的寫事務包括update和delete(只給存在的表加上了鎖),但是不包括insert(新行不存在,所以沒有辦法加鎖),所以一個事務第一次讀取可能讀取到了10條記錄,但是第二次可能讀取到11條,這就是幻讀。

      解決辦法就是下面的“串行化”。

    • 可串行化(Serializable)

      讀加共享鎖,寫加排他鎖。這樣讀取事務可以並發,但是讀寫,寫寫事務之間都是互斥的,基本上就是一個個執行事務,所以叫串行化。

 

  • 臟讀:

    事務A修改了一個數據,但未提交,事務B讀到了事務A未提交的更新結果,如果事務A提交失敗,事務B讀到的就是臟數據。

  • 不可重復讀:

    在同一個事務中,對於同一份數據讀取到的結果不一致。比如,事務B在事務A提交前讀到的結果,和提交后讀到的結果可能不同。

  • 幻讀:

    在同一個事務中,同一個查詢多次返回的結果不一致。通常是因為在事務A中進行了一次全局操作,如新增了一條記錄;事務B在事務A提交前后各執行了一次查詢操作,發現后一次比前一次多了一條記錄。

 

  • 優化行級鎖


1、精心設計索引,盡量使用索引訪問數據
2、選擇合理的事務,小事務發生鎖沖突的幾率小
3、給記錄集手動加鎖,最好一次性請求足夠級別的鎖(寫鎖級別>讀鎖級別),不要先申請共享再申請排他。
4、盡量用相等的條件訪問數據,這樣可以避免間隙鎖對並發插入的影響
5、對於一些特定事務,可以使用表鎖來提高處理速度或減少死鎖的可能。(購物,三表同時修改 庫存,銷售記錄,購 物車)

 

 

  • 練習


課程表   id   課程名   老師id

老師表     id   姓名   簡介id

簡介表     id   信息      

查看 帶python老師的信息 3種

1、select iname from info where id=(select iid from teacher where id=(select tid from class where cid=1));

2、 SELECT iname FROM info,class,teacher where info.id=teacher.iid and class.tid=teacher.id and class.cid=1;

3、 select iname FROM info INNER join teacher on info.id=teacher.iid INNER JOIN class on teacher.id=class.tid where class.cid=1;

4、select iname from info join teacher on info.id=teacher.iid where teacher.id=(select tid from class where cid=1);
  • explain+語句 測速率 分析語句合理性

主從復制

實際生產中,有單台MySQL數據庫是完全不滿足實際需求,無論安全性,高可用性以及高並發性等各方面要求。而主從mysql會實現mysql的實時備份,高可用,讀寫分離場景。

  • 原理

 

  • 配置過程

    • 兩台服務器

    • 雙方mysql版本一致,如果不一致,從結點高於主節點

    • 服務器防火牆要關閉掉

      sudo ufw status ubuntu系統

    • 上方數據庫用戶需要具有遠程訪問的權限

  • 修改主服務器的MySQL的配置文件 window 放到(my.ini)的mysqld下面 linux(my.cnf)


    #mysql 唯一id
    server-id=1
    #二進制文件,此項為必填項,否則不能同步數據 (可以加路徑)
    log-bin="mysql-bin"
    #指定二進制錯誤文件所放的位置
    log-error="mysql-error"
    #需同步的數據庫 如果需要同步多個
    binlog-do-db=wangwei
    #binlog-do-db="表名"

    #不需要同步的數據庫
    binlog-ignore=mysql

    read_only   #只讀  
  • 給從數據庫授權(可以從主服務器取數據)


grant replication slave on *.* to 'root'@'192.168.2.155' identified by '9264934.。' flush privileges;
  • 重啟服務器(數據庫服務)


service mysqld restart   #
  • 查看主服務器狀態


    show master status;
  • 從服務器配置

    1.修改從服務器的mysql配置文件,注意ID沒有被別的mysql服務占用


    server-id = 2
    log-bin = "mysql-bin"
    replicate-do-db =wangwei
    replicate-ignore-db = mysql

    2.重啟mysql服務

    3.執行同步sql語句

    change master to
    master_host='192.168.217.135', #設置要連接的主服務器IP地址master_user='root', #設置要連接的主服務器用戶名
    master_password='123456', #設置要連接的主服務器密碼
    master_log_file='mysql-bin.000002', #設置要連接的主服務器bin日志的日志名稱
    master_log_pos=1041; #設置要連接的主服務器bin日志的記錄位置
    
    
    change master to
    master_host = '192.168.217.135',
    master_user = 'root',
    master_password = '123456',
    master_log_file = 'mysql-bin.000008',
    master_log_pos = 107;
    

    4.啟動slave同步進程


    start slave
    #查看狀態
    show slave status\G   # 查看同步狀態
    #其中Slave_IO_Running Slave_SQL_Running值都是YES,表示狀態正常
    #如果之前從服務器啟動過需要先停止在運行
    stop slave
  • 查看二進制信息


    show binary logs;   #二進制文件
    show master logs;   #當前使用的
  • 刪除二進制文件


    purge binary logs to "mysql-bin.000002";     #刪除此文件之前的文件
    • 自動清理


    show variable like "expire_logs_day"

    set expire_logs_day=7   #7天自動清理一次

優化

  • 表級優化(鎖)

  • 系統優化

    • 主從復制

    • 負載均衡

    • 讀寫分離

 

多表查詢,小表在前,大表在后 (where 小表 .x = 大表.y)

left join 給左邊的表加索引,right 給右邊的表加索引

  • explain

  1. id:

    • 相同時,由上至下

    • 不同時,從大到小

  • 查詢語句


    select * fgroup by
    distanc+-1
  • 派生表

    在查詢內容再查詢


    select aa..cname from (select cname,tid from class) as aa;
  • type

    從表中找到自己想要的數據的方式

    ALL<index<range<ref<eq_ref<const<system<NULL


    ALL:遍歷全表找到匹配的行,並且查找的內容不帶索引
    index:只遍歷索引樹,查找索引的列     #加索引
    range: 檢索給定的范圍,查找的內容不帶索引,選擇的行帶索引   #id<10 盡量不用in in會破壞掉索引
    ref:確定的一個值    #where name="zhangsan"
    eq_ref:類似ref,區別就在於使用的是唯一索引 unique
    const:主鍵關聯,主鍵查詢
    system:
  • key_len

    索引所占的內存空間 utf8 英文占3字節 中文占4字節

  • Extra

    額外信息:

    1、Using:temporary: 需要額外的內存存儲信息
    
    2、Impossible whe:條件有問題
    
    3、Using filesort:  多次排序,沒有索引
    

    復合索引:最佳左前綴;

 

篩選需優化的內容

用慢查詢日志篩選  自己指定一個時間,超出long_time的語句會存到慢查詢的日志中,然后在日志中找到那條語句用explain檢測。


優化索引

可以把要查找的內容加上索引來補救

  • 不能將索引作為表達式的一部分,也不能作為參數,否則索引失效


    explain select * from class where id+1=1
    explain select tname from teacher where left(tname,3)="";  #沒有索引
  • 索引不能做類型轉化


    explain select iid from teacher where tname=111   #tname varchar() "1111"
  • 符合索引遵循左前綴策略

  • 索引不能跟or 否則全部失效;

  • 復合索引不能有不等號 <> != 或者is null

  • 不能用in 可以用between

  • 及時刪除不用的索引

  • like 查詢時盡量不要出現左邊的“%”


    explain select iid from teacher where tname like "%xx";

其他優化

  1. 把NULL改成NOT NULL

  2. 根據業務,盡可能選擇小的存儲數據類型

  3. unsigned 表示不允許復制 -127~128 = 0~255

  4. timestamp(時間戳) 使用4個字節, 而 datetime 使用8個字節

  5. 基本沒有使用enum(枚舉)

  6. 盡量少列 不大於10列

  7. 應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。

  8. 應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: select id from t where num is null 可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢: select id from t where num=0

  9. 很多時候用 exists 代替 in 是一個好的選擇

  10. 用Where子句替換HAVING 子句 因為HAVING 只會在檢索出所有記錄之后才對結果集進行過濾


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM