MySQL高階

Gaowaly發表於2021-03-07

閱讀目錄:

1.檢視

2.事務

3.索引

4.賬戶管理(瞭解)

5.MySQL主從

一.檢視

1. 問題

對於複雜的查詢,往往是有多個資料表進行關聯查詢而得到,如果資料庫因為需求等原因發生了改變,為了保證查詢出來的資料與之前相同,則需要在多個地方進行修改,維護起來非常麻煩

解決辦法:定義檢視

2. 檢視是什麼

通俗的講,檢視就是一條SELECT語句執行後返回的結果集。所以我們在建立檢視的時候,主要的工作就落在建立這條SQL查詢語句上。

檢視是對若干張基本表的引用,一張虛表,查詢語句執行的結果,不儲存具體的資料(基本表資料發生了改變,檢視也會跟著改變);

方便操作,特別是查詢操作,減少複雜的SQL語句,增強可讀性;

3. 定義檢視

建議以v_開頭

create view 檢視名稱 as select語句;

 

4. 檢視檢視

檢視錶會將所有的檢視也列出來

show tables;

 

5. 使用檢視

檢視的用途就是查詢

select * from v_stu_score;

 

6. 刪除檢視

drop view 檢視名稱;
例:
drop view v_stu_sco;

 

7. 檢視demo

MySQL高階

MySQL高階

MySQL高階

 

 

MySQL高階

8. 檢視的作用

  1. 提高了重用性,就像一個函式
  2. 對資料庫重構,卻不影響程式的執行
  3. 提高了安全效能,可以對不同的使用者
  4. 讓資料更加清晰

二.事務

1. 為什麼要有事務

事務廣泛的運用於訂單系統、銀行系統等多種場景

例如:

A使用者和B使用者是銀行的儲戶,現在A要給B轉賬500元,那麼需要做以下幾件事:

  1. 檢查A的賬戶餘額>500元;
  2. A 賬戶中扣除500元;
  3. B 賬戶中增加500元;

正常的流程走下來,A賬戶扣了500,B賬戶加了500,皆大歡喜。

那如果A賬戶扣了錢之後,系統出故障了呢?A白白損失了500,而B也沒有收到本該屬於他的500。

以上的案例中,隱藏著一個前提條件:A扣錢和B加錢,要麼同時成功,要麼同時失敗。事務的需求就在於此

所謂事務,它是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。

例如,銀行轉帳工作:從一個帳號扣款並使另一個帳號增款,這兩個操作要麼都執行,要麼都不執行。所以,應該把他們看成一個事務。事務是資料庫維護資料一致性的單位,在每個事務結束時,都能保持資料一致性

事務四大特性(簡稱ACID)

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔離性(Isolation)
  • 永續性(Durability)

以下內容出自《高效能MySQL》第三版,瞭解事務的ACID及四種隔離級有助於我們更好的理解事務運作。

下面舉一個銀行應用是解釋事務必要性的一個經典例子。假如一個銀行的資料庫有兩張表:支票表(checking)和儲蓄表(savings)。現在要從使用者Jane的支票賬戶轉移200美元到她的儲蓄賬戶,那麼至少需要三個步驟:

  1. 檢查支票賬戶的餘額高於或者等於200美元。
  2. 從支票賬戶餘額中減去200美元。
  3. 在儲蓄帳戶餘額中增加200美元。

上述三個步驟的操作必須打包在一個事務中,任何一個步驟失敗,則必須回滾所有的步驟。

可以用START TRANSACTION語句開始一個事務,然後要麼使用COMMIT提交將修改的資料持久儲存,要麼使用ROLLBACK撤銷所有的修改。事務SQL的樣本如下:

  1. start transaction;
  2. select balance from checking where customer_id = 10233276;
  3. update checking set balance = balance - 200.00 where customer_id = 10233276;
  4. update savings set balance = balance + 200.00 where customer_id = 10233276;
  5. commit;

一個很好的事務處理系統,必須具備這些標準特性:

  • 原子性(atomicity)

一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要麼全部提交成功,要麼全部失敗回滾,對於一個事務來說,不可能只執行其中的一部分操作,這就是事務的原子性

  • 一致性(consistency)

資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態。(在前面的例子中,一致性確保了,即使在執行第三、四條語句之間時系統崩潰,支票賬戶中也不會損失200美元,因為事務最終沒有提交,所以事務中所做的修改也不會儲存到資料庫中。)

  • 隔離性(isolation)

通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的。(在前面的例子中,當執行完第三條語句、第四條語句還未開始時,此時有另外的一個賬戶彙總程式開始執行,則其看到支票帳戶的餘額並沒有被減去200美元。)

  • 永續性(durability)

一旦事務提交,則其所做的修改會永久儲存到資料庫。(此時即使系統崩潰,修改的資料也不會丟失。)

事務命令

表的引擎型別必須是innodb型別才可以使用事務,這是mysql表的預設引擎

檢視錶的建立語句,可以看到engine=innodb

-- 選擇資料庫
use jing_dong;
-- 檢視goods表
show create table goods;

 

開啟事務,命令如下:

  • 開啟事務後執行修改命令,變更會維護到本地快取中,而不維護到物理表中
begin;
或者
start transaction;

 

提交事務,命令如下

  • 將快取中的資料變更維護到物理表中
commit;

 

回滾事務,命令如下:

  • 放棄快取中變更的資料
rollback;

 

注意

  1. 修改資料的命令會自動的觸發事務,包括insert、update、delete
  2. 而在SQL語句中有手動開啟事務的原因是:可以進行多次資料的修改,如果成功一起成功,否則一起會滾到之前的資料

提交

  • 為了演示效果,需要開啟兩個終端視窗,使用同一個資料庫,操作同一張表(用到之前的jing_dong資料,可以回到mysql第3天中檢視)

step1:連線

  • 終端1:查詢商品分類資訊
select * from goods_cates;

 

step2:增加資料

  • 終端2:開啟事務,插入資料
begin;
insert into goods_cates(name) values('小霸王遊戲機');

 

  • 終端2:查詢資料,此時有新增的資料
select * from goods_cates;

 

step3:查詢

  • 終端1:查詢資料,發現並沒有新增的資料
select * from goods_cates;

 

step4:提交

  • 終端2:完成提交
commit;

 

step5:查詢

  • 終端1:查詢,發現有新增的資料
select * from goods_cates;

回滾

  • 為了演示效果,需要開啟兩個終端視窗,使用同一個資料庫,操作同一張表

step1:連線

  • 終端1
select * from goods_cates;

 

step2:增加資料

  • 終端2:開啟事務,插入資料
begin;
insert into goods_cates(name) values('小霸王遊戲機');

 

  • 終端2:查詢資料,此時有新增的資料
select * from goods_cates;

 

step3:查詢

  • 終端1:查詢資料,發現並沒有新增的資料
select * from goods_cates;

 

step4:回滾

  • 終端2:完成回滾
rollback;

 

step5:查詢

  • 終端1:查詢資料,發現沒有新增的資料
select * from goods_cates;

三.索引

1. 思考

在圖書館中是如何找到一本書的?

一般的應用系統對比資料庫的讀寫比例在10:1左右(即有10次查詢操作時有1次寫的操作),

而且插入操作和更新操作很少出現效能問題,

遇到最多、最容易出問題還是一些複雜的查詢操作,所以查詢語句的優化顯然是重中之重

2. 解決辦法

當資料庫中資料量很大時,查詢資料會變得很慢

優化方案:索引

3. 索引是什麼

索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標。

更通俗的說,資料庫索引好比是一本書前面的目錄,能加快資料庫的查詢速度

4. 索引目的

索引的目的在於提高查詢效率,可以類比字典,如果要查“mysql”這個單詞,我們肯定需要定位到m字母,然後從下往下找到y字母,再找到剩下的sql。如果沒有索引,那麼你可能需要把所有單詞看一遍才能找到你想要的,如果我想找到m開頭的單詞呢?或者ze開頭的單詞呢?是不是覺得如果沒有索引,這個事情根本無法完成?

5. 索引原理

除了詞典,生活中隨處可見索引的例子,如火車站的車次表、圖書的目錄等。它們的原理都是一樣的,通過不斷的縮小想要獲得資料的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是我們總是通過同一種查詢方式來鎖定資料。

資料庫也是一樣,但顯然要複雜許多,因為不僅面臨著等值查詢,還有範圍查詢(>、<、between、in)、模糊查詢(like)、並集查詢(or)等等。資料庫應該選擇怎麼樣的方式來應對所有的問題呢?我們回想字典的例子,能不能把資料分成段,然後分段查詢呢?最簡單的如果1000條資料,1到100分成第一段,101到200分成第二段,201到300分成第三段……這樣查第250條資料,只要找第三段就可以了,一下子去除了90%的無效資料。

6. 索引的使用

  • 檢視索引
show index from 表名;

 

  • 建立索引
    • 如果指定欄位是字串,需要指定長度,建議長度與定義欄位時的長度一致
    • 欄位型別如果不是字串,可以不填寫長度部分
create index 索引名稱 on 表名(欄位名稱(長度))

 

  • 刪除索引:
drop index 索引名稱 on 表名;

 

7. 索引demo

7.1. 建立測試表testindex

create table test_index(title varchar(10));

 

7.2 使用python程式(ipython也可以)通過pymsql模組 向表中加入十萬條資料

from pymysql import connect

def main():
    # 建立Connection連線
    conn = connect(host='localhost',port=3306,database='jing_dong',user='root',password='mysql',charset='utf8')
    # 獲得Cursor物件
    cursor = conn.cursor()
    # 插入10萬次資料
    for i in range(100000):
        cursor.execute("insert into test_index values('ha-%d')" % i)
    # 提交資料
    conn.commit()

if __name__ == "__main__":
    main()

 

7.3. 查詢

  • 開啟執行時間監測:
set profiling=1;

 

  • 查詢第1萬條資料ha-99999
select * from test_index where title='ha-99999';

 

  • 檢視執行的時間:
show profiles;

 

  • 為表title_index的title列建立索引:
create index title_index on test_index(title(10));

 

  • 執行查詢語句:
select * from test_index where title='ha-99999';

 

  • 再次檢視執行的時間
show profiles;

 

8. 注意:

要注意的是,建立太多的索引將會影響更新和插入的速度,因為它需要同樣更新每個索引檔案。對於一個經常需要更新和插入的表格,就沒有必要為一個很少使用的where字句單獨建立索引了,對於比較小的表,排序的開銷不會很大,也沒有必要建立另外的索引。

建立索引會佔用磁碟空間

四.賬戶管理

  • 在生產環境下運算元據庫時,絕對不可以使用root賬戶連線,而是建立特定的賬戶,授予這個賬戶特定的操作許可權,然後連線進行操作,主要的操作就是資料的crud
  • MySQL賬戶體系:根據賬戶所具有的許可權的不同,MySQL的賬戶可以分為以下幾種賬戶的操作主要包括建立賬戶、刪除賬戶、修改密碼、授權許可權等
    • 服務例項級賬號:,啟動了一個mysqld,即為一個資料庫例項;如果某使用者如root,擁有服務例項級分配的許可權,那麼該賬號就可以刪除所有的資料庫、連同這些庫中的表
    • 資料庫級別賬號:對特定資料庫執行增刪改查的所有操作
    • 資料表級別賬號:對特定表執行增刪改查等所有操作
    • 欄位級別的許可權:對某些表的特定欄位進行操作
    • 儲存程式級別的賬號:對儲存程式進行增刪改查的操作

注意:

  1. 進行賬戶操作時,需要使用root賬戶登入,這個賬戶擁有最高的例項級許可權
  2. 通常都使用資料庫級操作許可權

授予許可權

需要使用例項級賬戶登入後操作,以root為例

主要操作包括:

  • 檢視所有使用者
  • 修改密碼
  • 刪除使用者

1. 檢視所有使用者

  • 所有使用者及許可權資訊儲存在mysql資料庫的user表中
  • 檢視user表的結構
desc user;

 

  • 主要欄位說明:
    • Host表示允許訪問的主機
    • User表示使用者名稱
    • authentication_string表示密碼,為加密後的值

檢視所有使用者

select host,user,authentication_string from user;

 

結果

mysql> select host,user,authentication_string from user;
+-----------+------------------+-------------------------------------------+
| host      | user             | authentication_string                     |
+-----------+------------------+-------------------------------------------+
| localhost | root             | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| localhost | mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | debian-sys-maint | *EFED9C764966EDB33BB7318E1CBD122C0DFE4827 |
+-----------+------------------+-------------------------------------------+
3 rows in set (0.00 sec)

 

2. 建立賬戶、授權

  • 需要使用例項級賬戶登入後操作,以root為例
  • 常用許可權主要包括:create、alter、drop、insert、update、delete、select
  • 如果分配所有許可權,可以使用all privileges

2.1 建立賬戶&授權

grant 許可權列表 on 資料庫 to '使用者名稱'@'訪問主機' identified by '密碼';

 

2.2 示例1

建立一個laowang的賬號,密碼為123456,只能通過本地訪問, 並且只能對jing_dong資料庫中的所有表進行操作

step1:使用root登入
mysql -uroot -p
回車後寫密碼,然後回車

 

step2:建立賬戶並授予所有許可權
grant select on jing_dong.* to 'laowang'@'localhost' identified by '123456';

 

說明

  • 可以操作python資料庫的所有表,方式為:jing_dong.*
  • 訪問主機通常使用 百分號% 表示此賬戶可以使用任何ip的主機登入訪問此資料庫
  • 訪問主機可以設定成 localhost或具體的ip,表示只允許本機或特定主機訪問
  • 檢視使用者有哪些許可權
show grants for laowang@localhost;

 

step3:退出root的登入
quit

 

step4:使用laowang賬戶登入
mysql -ulaowang -p
回車後寫密碼,然後回車

 

  • 登入後效果如下圖

MySQL高階

 

 

 MySQL高階

2.3 示例2

建立一個laoli的賬號,密碼為12345678,可以任意電腦進行連結訪問, 並且對jing_dong資料庫中的所有表擁有所有許可權

grant all privileges on jing_dong.* to "laoli"@"%" identified by "12345678"

MySQL高階

 

 

 MySQL高階

 

 

 MySQL高階

賬戶操作

1. 修改許可權

grant 許可權名稱 on 資料庫 to 賬戶@主機 with grant option;

MySQL高階

 

 

 MySQL高階

 

 

 MySQL高階

2. 修改密碼

使用root登入,修改mysql資料庫的user表

  • 使用password()函式進行密碼加密

    update user set authentication_string=password('新密碼') where user='使用者名稱';
    例:
    update user set authentication_string=password('123') where user='laowang';

     

  • 注意修改完成後需要重新整理許可權

    重新整理許可權:flush privileges

     

3. 遠端登入(危險慎用)

如果向在一個Ubuntu中使用msyql命令遠端連線另外一臺mysql伺服器的話,通過以下方式即可完成,但是此方法僅僅瞭解就好了,不要在實際生產環境中使用

修改 /etc/mysql/mysql.conf.d/mysqld.cnf 檔案

vim /etc/mysql/mysql.conf.d/mysqld.cnf

MySQL高階

然後重啟msyql

service mysql restart

 

在另外一臺Ubuntu中進行連線測試

MySQL高階

如果依然連不上,可能原因:

1) 網路不通

通過 ping xxx.xxx.xx.xxx可以發現網路是否正常

2)檢視資料庫是否配置了bind_address引數

本地登入資料庫檢視my.cnf檔案和資料庫當前引數show variables like 'bind_address';

如果設定了bind_address=127.0.0.1 那麼只能本地登入

3)檢視資料庫是否設定了skip_networking引數

如果設定了該引數,那麼只能本地登入mysql資料庫

4)埠指定是否正確

4. 刪除賬戶

  • 語法1:使用root登入
drop user '使用者名稱'@'主機';
例:
drop user 'laowang'@'%';

 

  • 語法2:使用root登入,刪除mysql資料庫的user表中資料
delete from user where user='使用者名稱';
例:
delete from user where user='laowang';

-- 操作結束之後需要重新整理許可權
flush privileges

 

  • 推薦使用語法1刪除使用者, 如果使用語法1刪除失敗,採用語法2方式

3. 忘記 root 賬戶密碼怎麼辦 !!

五.MySQL主從同步配置

1. 主從同步的定義

主從同步使得資料可以從一個資料庫伺服器複製到其他伺服器上,在複製資料時,一個伺服器充當主伺服器(master),其餘的伺服器充當從伺服器(slave)。因為複製是非同步進行的,所以從伺服器不需要一直連線著主伺服器,從伺服器甚至可以通過撥號斷斷續續地連線主伺服器。通過配置檔案,可以指定複製所有的資料庫,某個資料庫,甚至是某個資料庫上的某個表。

使用主從同步的好處:

  • 通過增加從伺服器來提高資料庫的效能,在主伺服器上執行寫入和更新,在從伺服器上向外提供讀功能,可以動態地調整從伺服器的數量,從而調整整個資料庫的效能。
  • 提高資料安全,因為資料已複製到從伺服器,從伺服器可以終止複製程式,所以,可以在從伺服器上備份而不破壞主伺服器相應資料
  • 在主伺服器上生成實時資料,而在從伺服器上分析這些資料,從而提高主伺服器的效能

2. 主從同步的機制

 

 

 

Mysql伺服器之間的主從同步是基於二進位制日誌機制,主伺服器使用二進位制日誌來記錄資料庫的變動情況,從伺服器通過讀取和執行該日誌檔案來保持和主伺服器的資料一致。

在使用二進位制日誌時,主伺服器的所有操作都會被記錄下來,然後從伺服器會接收到該日誌的一個副本。從伺服器可以指定執行該日誌中的哪一類事件(譬如只插入資料或者只更新資料),預設會執行日誌中的所有語句。

每一個從伺服器會記錄關於二進位制日誌的資訊:檔名和已經處理過的語句,這樣意味著不同的從伺服器可以分別執行同一個二進位制日誌的不同部分,並且從伺服器可以隨時連線或者中斷和伺服器的連線。

主伺服器和每一個從伺服器都必須配置一個唯一的ID號(在my.cnf檔案的[mysqld]模組下有一個server-id配置項),另外,每一個從伺服器還需要通過CHANGE MASTER TO語句來配置它要連線的主伺服器的ip地址,日誌檔名稱和該日誌裡面的位置(這些資訊儲存在主伺服器的資料庫裡)

3. 配置主從同步的基本步驟

有很多種配置主從同步的方法,可以總結為如下的步驟:

  1. 在主伺服器上,必須開啟二進位制日誌機制和配置一個獨立的ID
  2. 在每一個從伺服器上,配置一個唯一的ID,建立一個用來專門複製主伺服器資料的賬號
  3. 在開始複製程式前,在主伺服器上記錄二進位制檔案的位置資訊
  4. 如果在開始複製之前,資料庫中已經有資料,就必須先建立一個資料快照(可以使用mysqldump匯出資料庫,或者直接複製資料檔案)
  5. 配置從伺服器要連線的主伺服器的IP地址和登陸授權,二進位制日誌檔名和位置

4. 詳細配置主從同步的方法

主和從的身份可以自己指定,我們將虛擬機器Ubuntu中MySQL作為主伺服器,將Windows中的MySQL作為從伺服器。 在主從設定前,要保證Ubuntu與Windows間的網路連通。

4.1 備份主伺服器原有資料到從伺服器

如果在設定主從同步前,主伺服器上已有大量資料,可以使用mysqldump進行資料備份並還原到從伺服器以實現資料的複製。

4.1.1 在主伺服器Ubuntu上進行備份,執行命令:

mysqldump -uroot -pmysql --all-databases --lock-all-tables > ~/master_db.sql

說明

  • -u :使用者名稱
  • -p :示密碼
  • --all-databases :匯出所有資料庫
  • --lock-all-tables :執行操作時鎖住所有表,防止操作時有資料修改
  • ~/master_db.sql :匯出的備份資料(sql檔案)位置,可自己指定

4.1.2 在從伺服器Windows上進行資料還原

找到Windows上mysql命令的位置

新開啟的命令視窗,在這個視窗中可以執行類似在Ubuntu終端中執行的mysql命令

將從主伺服器Ubuntu中匯出的檔案複製到從伺服器Windows中,可以將其放在上面mysql命令所在的資料夾中,方便還原使用

在剛開啟的命令黑視窗中執行還原操作:

mysql –uroot –pmysql < master_db.sql

4.2 配置主伺服器master(Ubuntu中的MySQL)

4.2.1 編輯設定mysqld的配置檔案,設定log_bin和server-id

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

 

 

 

4.2.2 重啟mysql服務

sudo service mysql restart

4.2.3 登入主伺服器Ubuntu中的mysql,建立用於從伺服器同步資料使用的帳號

mysql –uroot –pmysql

 

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' identified by 'slave';

 

FLUSH PRIVILEGES;

4.2.4 獲取主伺服器的二進位制日誌資訊

SHOW MASTER STATUS;

File為使用的日誌檔名字,Position為使用的檔案位置,這兩個引數須記下,配置從伺服器時會用到

4.3 配置從伺服器slave(Windows中的MySQL)

4.3.1 找到Windows中MySQL的配置檔案

4.3.2 編輯my.ini檔案,將server-id修改為2,並儲存退出。

4.3.3 開啟windows服務管理

可以在開始選單中輸入services.msc找到並執行

4.3.4 在開啟的服務管理中找到MySQL57,並重啟該服務

5. 進入windows的mysql,設定連線到master主伺服器

change master to master_host='10.211.55.5', master_user='slave', master_password='slave',master_log_file='mysql-bin.000006', master_log_pos=590;

 

注:
  • master_host:主伺服器Ubuntu的ip地址
  • master_log_file: 前面查詢到的主伺服器日誌檔名
  • master_log_pos: 前面查詢到的主伺服器日誌檔案位置

6. 開啟同步,檢視同步狀態

7. 測試主從同步

在Ubuntu的MySQL中(主伺服器)建立一個資料庫

 

 在Windows的MySQL中(從伺服器)檢視新建的資料庫是否存在

 

相關文章