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
-
錯誤日志
-
查看錯誤日志地址
show global variables like ”log_error" -
警告信息開關
show global variables like "log_warnings"; #查看是否開啟 開啟為1,關閉為0
set global log_warnings=0 #關閉
-
-
一般查詢日志
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-
查看錯誤日志地址
show global variables like ”log_error" 警告信息開關2.2.錯誤警告開關
show global variables like "log_warnings"; #查看是否開啟 開啟為1,關閉為0
set global log_warnings=0 #關閉 -
-
慢查詢日志
放到配置文件中
查詢超時時間: 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;
子查詢
把一個查詢嵌套在另一個查詢,叫內部查詢
-
分類
-
標量子查詢:返回但一直的標量,最簡單的形式
-
列子查詢:返回結果是N行一列
-
行子查詢:返回結果為一行N列
-
表子查詢:返回結果為N行N列
-
-
標量子查詢(一個值)
select * from article where uid = (select uid from user where status=1 order by uid desc limit 1) in
-
關鍵字
anyallany :< > = <>條件中的任何一個就可以
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
-
cuncurrent_insert 為0時:不允許並發插入
-
cuncurrent_insert 為1:如果MyISAM沒有空洞:即使有鎖,也會從尾部插入 有空洞:不插入 (空洞:id=1,2,4 少3)
-
cuncurrent_insert 為2:加鎖的時候把 [local] 加上 allways 總是可以隊尾插入信息(鎖的情況下)
********很重要,用mysql就改成2set 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 statusubuntu系統 -
上方數據庫用戶需要具有遠程訪問的權限
-
-
修改主服務器的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 = mysql2.重啟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
-
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";
其他優化
-
把NULL改成NOT NULL
-
根據業務,盡可能選擇小的存儲數據類型
-
unsigned 表示不允許復制 -127~128 = 0~255
-
timestamp(時間戳) 使用4個字節, 而 datetime 使用8個字節
-
基本沒有使用enum(枚舉)
-
盡量少列 不大於10列
-
應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
-
應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: select id from t where num is null 可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢: select id from t where num=0
-
很多時候用 exists 代替 in 是一個好的選擇
-
用Where子句替換HAVING 子句 因為HAVING 只會在檢索出所有記錄之后才對結果集進行過濾
