高性能 SQL 計劃 Day 5

今天繼續(xù)學(xué)習(xí)《MySQL 必知必會》畜埋,今天是23章-30章的內(nèi)容。

Ch 23.使用存儲過程

所謂的存儲過程畴蒲,就是在需要針對多個表進行多條SQL語句處理的復(fù)雜場合悠鞍,將多條SQL語句保存成的一個集合。存儲過程相當(dāng)于一個SQL的集合函數(shù)模燥,封裝了若干條SQL語句咖祭。

1.存儲過程的優(yōu)缺點:

存儲過程主要有以下優(yōu)點:

  • 簡單

    • 通過把處理封裝在容易使用的單元中,簡化復(fù)雜的操作蔫骂。
    • 由于不要求反復(fù)建立一系列處理步驟么翰,這保證了數(shù)據(jù)的完整性。
  • 安全

    簡化對變動的管理辽旋。如果表名浩嫌、列名或業(yè)務(wù)邏輯(或別的內(nèi)容)有變化,只需要更改存儲過程的代碼戴已。使用它的人員甚至不需要知道這些變化固该。通過存儲過程可以限制對基礎(chǔ)數(shù)據(jù)的訪問,減少了數(shù)據(jù)訛傳糖儡。

  • 高性能

    • 提高性能伐坏。因為使用存儲過程比使用單獨的SQL語句要快。
    • 存在一些只能用在單個請求中的MySQL元素和特性握联,存儲過程可以使用它們來編寫功能更強更靈活的代碼桦沉。

存儲過程的缺點也很明顯:編寫存儲過程要比編寫基本的SQL語句復(fù)雜很多;存儲過程也往往存在一定的限制金闽,比如只允許用戶使用存儲過程而不允許創(chuàng)建纯露。

2.使用存儲過程

調(diào)用存儲過程

MySQL 調(diào)用執(zhí)行過程使用的是 CALL關(guān)鍵字,如:

CALL productpricing(@pricelow,
                    @pricehigh,
                    @priceaverage);                    
#CALL 存儲過程名(參數(shù)列表);

創(chuàng)建存儲過程

以下創(chuàng)建了一個簡單的無參的存儲過程:

CREATE PROCEDURE productpricing()
BEGIN
   SELECT Avg(prod_price) AS priceaverage
   FROM products;
END;

#CREATE PROCEDURE (參數(shù)列表)
#BEGIN
#   SQL 語句
#END;

注意:如果使用的是命令行版的MySQL代芜,存儲過程體中的SQL語句中的;會被作為分隔符使用埠褪,造成錯誤。解決措施是臨時臨時更改命令行版MySQL的語句分隔符:

#將分隔符替換為//
DELIMITER //

  CREATE PROCEDURE productpricing()
  BEGIN
     SELECT Avg(prod_price) AS priceaverage
     FROM products;
  END //

  DELIMITER ;
#將分隔符改回;

除了\符號外挤庇,其他的符號都可以作為命令行 MySQL 的分隔符钞速。

調(diào)用上述存儲過程:

CALL productpricing();

刪除存儲過程

刪除上述存儲過程:

DROP PROCEDURE productpricing;
#存儲過程名后面不需要帶()
#僅存在時刪除:DROP PROCEDURE IF EXISTS

使用參數(shù)

使用存儲過程時嫡秕,常常將結(jié)果存儲到某個變量里面渴语,因此需要在存儲過程中使用參數(shù)傳遞變量:

CREATE PROCEDURE productpricing(
   OUT pl DECIMAL(8,2),
   OUT ph DECIMAL(8,2),
   OUT pa DECIMAL(8,2)
)
BEGIN
   SELECT Min(prod_price)
   INTO pl
   FROM products;
   SELECT Max(prod_price)
   INTO ph
   FROM products;
   SELECT Avg(prod_price)
   INTO pa
   FROM products;
END;

此存儲過程接受3個參數(shù):pl存儲產(chǎn)品最低價格,ph存儲產(chǎn)品最高價格昆咽,pa存儲產(chǎn)品平均價格驾凶。每個參數(shù)必須具有指定的類型牙甫,這里使用十進制值。關(guān)鍵字OUT指出相應(yīng)的參數(shù)用來從存儲過程傳出一個值(返回給調(diào)用者)调违。MySQL支持IN(傳遞給存儲過程)窟哺、OUT(從存儲過程傳出,如這里所用)和INOUT(對存儲過程傳入和傳出)類型的參數(shù)翰萨。存儲過程的代碼位于BEGIN和END語句內(nèi)脏答,如前所見糕殉,它們是一系列SELECT語句亩鬼,用來檢索值,然后保存到相應(yīng)的變量(通過指定INTO關(guān)鍵字)阿蝶。

注意:使用變量時雳锋,尤其是對變量進行賦值時需要注意變量的數(shù)據(jù)類型。

調(diào)用上述存儲過程羡洁,并輸出結(jié)果:

CALL productpricing(@pricelow,
                    @pricehigh,
                    @priceaverage);
SELECT @priceaverage;                    

注意:所有MySQL變量都需要使用@玷过。

以下是一個使用 IN 和 OUT 變量的存儲過程:

CREATE PROCEDURE ordertotal(
   IN onumber INT,
   OUT ototal DECIMAL(8,2)
)
BEGIN
   SELECT Sum(item_price*quantity)
   FROM orderitems
   WHERE order_num = onumber
   INTO ototal;
END;

調(diào)用上述存儲過程并輸出結(jié)果:

CALL ordertotal(20005,@total);
SELECT @total;

建立智能存儲過程

以下是聲明了一個復(fù)雜存儲過程:

-- Name: ordertotal
-- Parameters: onumber = order number
--             taxable = 0 if not taxable, 1 if taxable
--             ototal = order total variable

CREATE PROCEDURE ordertotal(
   IN onumber INT,
   IN taxable BOOLEAN,
   OUT ototal DECIMAL(8,2)
) COMMENT 'Obtain order total, optionally adding tax'
BEGIN

   -- Declare variable for total
   DECLARE total DECIMAL(8,2);
   -- Declare tax percentage
   DECLARE taxrate INT DEFAULT 6;

   -- Get the order total
   SELECT Sum(item_price*quantity)
   FROM orderitems
   WHERE order_num = onumber
   INTO total;

   -- Is this taxable?
   IF taxable THEN
      -- Yes, so add taxrate to the total
      SELECT total+(total/100*taxrate) INTO total;
   END IF;

   -- And finally, save to out variable
   SELECT total INTO ototal;

END;

注意以下幾點:

  • 增加了注釋 --。在編寫復(fù)雜的存儲過程時筑煮,添加一定的注視非常重要辛蚊。
  • 添加了另外一個參數(shù)taxable,它是一個布爾值真仲,傳入變量為0或1袋马。
  • 用DECLARE語句定義了兩個局部變量。
  • IF語句檢查taxable是否為真秸应,如果為真虑凛,則用另一SELECT語句增加營業(yè)稅到局部變量total。最后软啼,用另一SELECT語句將total(它增加或許不增加營業(yè)稅)保存到ototal桑谍。
  • 添加了COMMENT輸出信息,相當(dāng)于日志的作用祸挪,其信息將在SHOW PROCEDURE STATUS的結(jié)果中顯示锣披。

調(diào)用上述存儲過程,并輸出結(jié)果:

CALL ordertotal(20005, 0, @total);
SELECT @total;

檢查存儲過程

查看存儲過程的創(chuàng)建語句:

SHOW CREATE PROCEDURE ordertotal;

輸出存儲過程的詳細(xì)信息:

SHOW PROCEDURE STATUS;

以上語句會輸出全部的存儲過程的信息贿条,可以通過以下方式進行過濾:

SHOW PROCEDURE STATUS LIKE 'ordertotal';

Ch 24.使用游標(biāo)

SQL 檢索語句返回的結(jié)果稱為結(jié)果集雹仿,之前的操作無法完成這樣的操作:獲取下一行,獲取前十行等等闪唆。這就要使用游標(biāo)了盅粪。游標(biāo)主要用于交互式應(yīng)用,其中用戶需要滾動屏幕上的數(shù)據(jù)悄蕾,并對數(shù)據(jù)進行瀏覽或做出更改票顾。不同于其他DBMS础浮,MySQL的游標(biāo)只能用于存儲過程。

1.使用游標(biāo)

使用游標(biāo)涉及幾個明確的步驟:

  • 在能夠使用游標(biāo)前奠骄,必須聲明(定義)它豆同。這個過程實際上沒有檢索數(shù)據(jù),它只是定義要使用的SELECT語句含鳞。
  • 一旦聲明后影锈,必須打開游標(biāo)以供使用。這個過程用前面定義的SELECT語句把數(shù)據(jù)實際檢索出來蝉绷。
  • 對于填有數(shù)據(jù)的游標(biāo)鸭廷,根據(jù)需要取出(檢索)各行。
  • 在結(jié)束游標(biāo)使用時熔吗,必須關(guān)閉游標(biāo)辆床。

在聲明游標(biāo)后,可根據(jù)需要頻繁地打開和關(guān)閉游標(biāo)桅狠。在游標(biāo)打開后讼载,可根據(jù)需要頻繁地執(zhí)行取操作。

定義游標(biāo)

CREATE PROCEDURE processorders()
BEGIN
   DECLARE ordernumbers CURSOR
   FOR
   SELECT ordernum FROM orders;
END;

游標(biāo)的命名方式為DECLARE 游標(biāo)名 CURSOR中跌,需要注意的是咨堤,存儲過程執(zhí)行完畢后游標(biāo)就消失。

打開和關(guān)閉游標(biāo)

#打開游標(biāo)
OPEN ordernumbers;

#關(guān)閉游標(biāo)
CLOSE ordernumbers;

注意:只有打開游標(biāo)后才能使用它漩符,在游標(biāo)使用完畢后需要關(guān)閉它以釋放資源一喘。即使不手動關(guān)閉游標(biāo),當(dāng)存儲過程執(zhí)行完畢游標(biāo)也會被 MySQL 關(guān)閉陨仅。

CREATE PROCEDURE processorders()
BEGIN
   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;

   -- Open the cursor
   OPEN ordernumbers;

   -- Close the cursor
   CLOSE ordernumbers;

END;

使用游標(biāo)數(shù)據(jù)

在一個游標(biāo)被打開后津滞,可以使用FETCH語句分別訪問它的每一行。FETCH指定檢索什么數(shù)據(jù)(所需的列)灼伤,檢索出來的數(shù)據(jù)存儲在什么地方触徐。它還向前移動游標(biāo)中的內(nèi)部行指針,使下一條FETCH語句檢索下一行(不重復(fù)讀取同一行)狐赡。

第一個例子是利用FETCH檢索第一行

CREATE PROCEDURE processorders()
BEGIN

   -- Declare local variables
   DECLARE o INT;

   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;

   -- Open the cursor
   OPEN ordernumbers;

   -- Get order number
   --將檢索出的數(shù)據(jù)存放在局部變量o中
   FETCH ordernumbers INTO o;

   -- Close the cursor
   CLOSE ordernumbers;

END;

下一個例子是循環(huán)檢索數(shù)據(jù)撞鹉,從第一行到最后一行

CREATE PROCEDURE processorders()
BEGIN

   -- Declare local variables
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;

   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;

   -- Declare continue handler
   -- SQLSTATE '02000'指的是未找到的錯誤,強行類比的話像是NullPointerException
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

   -- Open the cursor
   OPEN ordernumbers;

   -- Loop through all rows
   REPEAT

      -- Get order number
      FETCH ordernumbers INTO o;

   -- End of loop
   UNTIL done END REPEAT;

   -- Close the cursor
   CLOSE ordernumbers;

END;

注意:DECLARE語句的發(fā)布存在特定的次序颖侄。用DECLARE語句定義的局部變量必須在定義任意游標(biāo)或句柄之前定義鸟雏,而句柄必須在游標(biāo)之后定義。不遵守此順序?qū)a(chǎn)生錯誤消息览祖。
接下來是一個復(fù)雜的例子孝鹊,其中ordertotal是上一章定義的一個計算稅率的存儲過程:

CREATE PROCEDURE processorders()
BEGIN

   -- Declare local variables
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;
   DECLARE t DECIMAL(8,2);

   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;
   -- Declare continue handler
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

   -- Create a table to store the results
   CREATE TABLE IF NOT EXISTS ordertotals
      (order_num INT, total DECIMAL(8,2));

   -- Open the cursor
   OPEN ordernumbers;

   -- Loop through all rows
   REPEAT

      -- Get order number
      FETCH ordernumbers INTO o;

      -- Get the total for this order
      CALL ordertotal(o, 1, t);

      -- Insert order and total into ordertotals
      INSERT INTO ordertotals(order_num, total)
      VALUES(o, t);

   -- End of loop
   UNTIL done END REPEAT;

   -- Close the cursor
   CLOSE ordernumbers;

END;

在這個存儲過程中,將檢索出來的數(shù)據(jù)存儲到新表中展蒂。

Ch 25.使用觸發(fā)器

如果想使得某些語句在一些事件發(fā)生后自動執(zhí)行又活,如每當(dāng)訂購一個產(chǎn)品時苔咪,都從庫存數(shù)量中減去訂購的數(shù)量;無論何時刪除一行柳骄,都在某個存檔表中保留一個副本团赏。想要完成這樣的操作,就要使用觸發(fā)器耐薯。

觸發(fā)器是MySQL響應(yīng)以下任意語句而自動執(zhí)行的一組MySQL語句:

  • DELETE舔清;
  • INSERT;
  • UPDATE曲初。

其他MySQL語句不支持觸發(fā)器体谒。

1.創(chuàng)建觸發(fā)器

創(chuàng)建觸發(fā)器需要提供以下信息:

  • 唯一的觸發(fā)器名;
  • 觸發(fā)器關(guān)聯(lián)的表复斥;
  • 觸發(fā)器應(yīng)該響應(yīng)的活動(DELETE营密、INSERT或UPDATE);
  • 觸發(fā)器何時執(zhí)行(處理之前或之后)目锭。

需要注意的是,最好是保持每個數(shù)據(jù)庫的觸發(fā)器名唯一纷捞。另外痢虹,只有表支持觸發(fā)器,視圖不支持主儡、臨時表也不支持奖唯。

CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SELECT 'Product added';

上述語句對 products 定義了一個觸發(fā)器,每當(dāng)對該表進行插入操作后糜值,對每個插入行顯示“Product added”消息丰捷。

MySQL 觸發(fā)器按每個表每個事件每次地定義,每個表每個事件每次只允許一個觸發(fā)器寂汇。因此病往,每個表最多支持6個觸發(fā)器,即INSERT骄瓣、DELETE停巷、UPDATE的執(zhí)行前和執(zhí)行后。

注意:在MySQL中榕栏,如果BEFORE觸發(fā)器失敗畔勤,則不會執(zhí)行請求的操作;如果BEFORE觸發(fā)器失敗或者語句本身失敗扒磁,也不會執(zhí)行AFTER觸發(fā)器操作庆揪。

2.刪除觸發(fā)器

DROP TRIGGER newproduct;

3.使用觸發(fā)器

INSERT觸發(fā)器

INSERT觸發(fā)器在INSERT語句執(zhí)行之前或之后執(zhí)行。需要知道以下幾點:

  • 在INSERT觸發(fā)器代碼內(nèi)妨托,可引用一個名為NEW的虛擬表缸榛,訪問被插入的行检访;
  • 在BEFORE INSERT觸發(fā)器中,NEW中的值也可以被更新(允許更改被插入的值)仔掸;
  • 對于AUTO_INCREMENT列脆贵,NEW在INSERT執(zhí)行之前包含0,在INSERT執(zhí)行之后包含新的自動生成值起暮。
CREATE TRIGGER neworder AFTER INSERT ON orders
FOR EACH ROW SELECT NEW.order_num;

上述語句定義了一個 neworder 的觸發(fā)器卖氨,在對orders表進行插入操作后對于每個插入行顯示該新插入記錄的order_num屬性值。

#運行如下語句
INSERT INTO orders(order_date, cust_id)
VALUES(Now(), 10001);

#可得到如下輸出
+-----------+
| order_num |
+-----------+
|     20010 |
+-----------+

注意:BEFORE觸發(fā)器多用于數(shù)據(jù)的驗證和凈化负懦,而AFTER觸發(fā)器多用于顯示提示信息筒捺。

DELETE觸發(fā)器

DELETE觸發(fā)器在DELETE語句執(zhí)行之前或之后執(zhí)行。需要知道以下兩點:

  • 在DELETE觸發(fā)器代碼內(nèi)纸厉,你可以引用一個名為OLD的虛擬表系吭,訪問被刪除的行;
  • OLD中的值全都是只讀的颗品,不能更新肯尺。

下面的例子演示使用OLD將要被刪除的行保存到一個存檔表中:

CREATE TRIGGER deleteorder BEFORE DELETE ON orders
FOR EACH ROW
BEGIN
   INSERT INTO archive_orders(order_num, order_date, cust_id)
   VALUES(OLD.order_num, OLD.order_date, OLD.cust_id);
END;
#觸發(fā)器體可以使用BEGIN和END包裹多條SQL語句。

根據(jù)前文所提到的躯枢,如果BEFORE觸發(fā)器執(zhí)行失敗则吟,則說明存檔失敗,因此不會執(zhí)行刪除操作锄蹂。

UPDATE觸發(fā)器

UPDATE觸發(fā)器在UPDATE語句執(zhí)行之前或之后執(zhí)行氓仲。需要知道以下幾點:

  • 在UPDATE觸發(fā)器代碼中,你可以引用一個名為OLD的虛擬表訪問以前(UPDATE語句前)的值得糜,引用一個名為NEW的虛擬表訪問新更新的值敬扛;
  • 在BEFORE UPDATE觸發(fā)器中,NEW中的值可能也被更新(允許更改將要用于UPDATE語句中的值)朝抖;
  • OLD中的值全都是只讀的啥箭,不能更新。

下面的例子保證州名縮寫總是大寫(不管UPDATE語句中給出的是大寫還是小寫):

CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors
FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);

注意事項

以下是原書中所寫的觸發(fā)器注意事項:

  • 與其他DBMS相比槽棍,MySQL5中支持的觸發(fā)器相當(dāng)初級捉蚤。未來的MySQL版本中有一些改進和增強觸發(fā)器支持的計劃。
  • 創(chuàng)建觸發(fā)器可能需要特殊的安全訪問權(quán)限炼七,但是缆巧,觸發(fā)器的執(zhí)行是自動的。如果INSERT豌拙、UPDATE或DELETE語句能夠執(zhí)行陕悬,則相關(guān)的觸發(fā)器也能執(zhí)行。
  • 應(yīng)該用觸發(fā)器來保證數(shù)據(jù)的一致性(大小寫按傅、格式等)捉超。在觸發(fā)器中執(zhí)行這種類型的處理的優(yōu)點是它總是進行這種處理胧卤,而且是透明地進行,與客戶機應(yīng)用無關(guān)拼岳。
  • 觸發(fā)器的一種非常有意義的使用是創(chuàng)建審計跟蹤枝誊。使用觸發(fā)器,把更改(如果需要惜纸,甚至還有之前和之后的狀態(tài))記錄到另一個表非常容易叶撒。
  • 遺憾的是,MySQL觸發(fā)器中不支持CALL語句耐版。這表示不能從觸發(fā)器內(nèi)調(diào)用存儲過程祠够。所需的存儲過程代碼需要復(fù)制到觸發(fā)器內(nèi)。

Ch 26.管理事務(wù)處理

正如前文所講的粪牲,并非所有的數(shù)據(jù)庫引擎都支持事務(wù)處理古瓤,MySQL最常用的引擎中,InnoDB支持事務(wù)而MyISAM不支持腺阳。

事務(wù)處理(transactionprocessing)可以用來維護數(shù)據(jù)庫的完整性落君,它保證成批的MySQL操作要么完全執(zhí)行,要么完全不執(zhí)行舌狗,以保證數(shù)據(jù)庫不包含不完整的操作結(jié)果叽奥。如果沒有錯誤發(fā)生,整組語句提交給(寫到)數(shù)據(jù)庫表痛侍。如果發(fā)生錯誤魔市,則進行回退(撤銷)以恢復(fù)數(shù)據(jù)庫到某個已知且安全的狀態(tài)主届。

首先定義幾個概念:

  • 事務(wù)(transaction)指一組SQL語句君丁;
  • 回退(rollback)指撤銷指定SQL語句的過程;
  • 提交(commit)指將未存儲的SQL語句結(jié)果寫入數(shù)據(jù)庫表将宪;
  • 保留點(savepoint)指事務(wù)處理中設(shè)置的臨時占位符(place-holder)绘闷,你可以對它發(fā)布回退(與回退整個事務(wù)處理不同)。

1.控制事務(wù)處理

管理事務(wù)處理的關(guān)鍵在于將SQL語句組分解為邏輯塊较坛,并明確規(guī)定數(shù)據(jù)何時應(yīng)該回退印蔗,何時不應(yīng)該回退。
MySQL使用下面的語句來標(biāo)識事務(wù)的開始:

START TRANSACTION

使用ROLLBACK

SELECT * FROM ordertotals;
START TRANSACTION;
DELETE FROM ordertotals;
SELECT * FROM ordertotals;
ROLLBACK;
SELECT * FROM ordertotals;

上述語句開啟事務(wù)后將ordertotals表中的記錄全部刪除丑勤,然后回滾事務(wù)华嘹,將數(shù)據(jù)庫狀態(tài)恢復(fù)至剛剛開啟事務(wù)時。

注意:只能回退INSERT法竞、UPDATE耙厚、DELETE語句强挫,SELECT語句回退沒有意義。不能回退CREATE和DROP薛躬,雖然可以在事務(wù)處理塊中使用這兩種語句锋拖,但是執(zhí)行回退他們不會被撤銷。

使用COMMIT

一般的MySQL語句都是直接針對數(shù)據(jù)庫表執(zhí)行和編寫的妨猩。這就是所謂的隱含提交(implicitcommit)捎泻,即提交(寫或保存)操作是自動進行的。但是诡曙,在事務(wù)處理塊中臀叙,提交不會隱含地進行。為進行明確的提交价卤,使用COMMIT語句劝萤。

START TRANSACTION;
DELETE FROM orderitems WHERE order_num = 20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT;

最后的COMMIT語句僅在不出錯時寫出更改。如果第一條DELETE起作用慎璧,但第二條失敗床嫌,則DELETE不會提交(實際上,它是被自動撤銷的)胸私。

注意:當(dāng)COMMIT或ROLLBACK語句執(zhí)行后厌处,事務(wù)會自動關(guān)閉(將來的更改會隱含提交)。

使用保留點

更復(fù)雜的事務(wù)處理可能需要部分提交或回退岁疼,為了支持回退部分事務(wù)處理阔涉,必須能在事務(wù)處理塊中合適的位置放置占位符。這樣捷绒,如果需要回退瑰排,可以回退到某個占位符。這些占位符稱為保留點暖侨。為了創(chuàng)建占位符椭住,可如下使用SAVEPOINT語句:

SAVEPOINT delete1;

#回退到保留點
ROLLBACK TO delete1;

注意:在進行復(fù)雜的事務(wù)操作時,可以盡可能多地設(shè)置保留點字逗,這樣可以靈活回退京郑。保留點在事務(wù)完成后會自動釋放,但也可以使用RELEASE SAVEPOINT明確地釋放保留點葫掉。

2.更改默認(rèn)的自動提交

默認(rèn)的MySQL行為是自動提交所有更改些举。換句話說,任何時候你執(zhí)行一條MySQL語句挖息,該語句實際上都是針對表執(zhí)行的金拒,而且所做的更改立即生效。為指示MySQL不自動提交更改,需要使用以下語句:

SET autocommit=0;

注意:autocommit標(biāo)志是針對每個連接而不是服務(wù)器的绪抛。

Ch 27.全球化和本地化

1.使用字符集和校正順序

查看MySQL所支持字符集的完整列表:

SHOW CHARACTER SET;

查看所支持的校正順序的完整列表:

SHOW COLLATION;

確定所使用的字符集和校正順序:

SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation%';

在創(chuàng)建表時指定字符集和校正順序:

CREATE TABLE mytable
(
   columnn1   INT,
   columnn2   VARCHAR(10)
) DEFAULT CHARACTER SET hebrew
  COLLATE hebrew_general_ci;

一般资铡,MySQL如下確定使用什么樣的字符集和校對:

  • 如果指定CHARACTER SET和COLLATE兩者,則使用這些值幢码。
  • 如果只指定CHARACTER SET笤休,則使用此字符集及其默認(rèn)的校對(如SHOW CHARACTER SET的結(jié)果中所示)。
  • 如果既不指定CHARACTER SET症副,也不指定COLLATE店雅,則使用數(shù)據(jù)庫默認(rèn)。

MySQL還允許對每個列設(shè)置字符集和校正順序:

CREATE TABLE mytable
(
   columnn1   INT,
   columnn2   VARCHAR(10),
   column3    VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci
) DEFAULT CHARACTER SET hebrew
  COLLATE hebrew_general_ci;

校對在對用ORDER BY子句檢索出來的數(shù)據(jù)排序時起重要的作用贞铣。如果你需要用與創(chuàng)建表時不同的校對順序排序特定的SELECT語句闹啦,可以在SELECT語句自身中進行:

SELECT * FROM customers
ORDER BY lastname, firstname COLLATE latin1_general_cs;

Ch 28.安全管理

1.訪問控制

MySQL服務(wù)器的安全基礎(chǔ)是:用戶應(yīng)該對他們需要的數(shù)據(jù)具有適當(dāng)?shù)脑L問權(quán),既不能多也不能少辕坝。

MySQL默認(rèn)數(shù)據(jù)庫的用戶root擁有對數(shù)據(jù)庫的絕對管理權(quán)限窍奋,應(yīng)該嚴(yán)肅對待root登錄的使用。僅在絕對需要時使用它(或許在你不能登錄其他管理賬號時使用)酱畅。不應(yīng)該在日常的MySQL操作中使用root琳袄。

2.管理用戶

MySQL用戶賬號和信息存儲在名為mysql的MySQL數(shù)據(jù)庫中》乃幔可以在其中的user表中查詢到所有的用戶:

USE mysql;
SELECT user FROM user;

創(chuàng)建用戶

CREATE USER ben IDENTIFIED BY 'p@$$w0rd';

重命名用戶

RENAME USER ben TO bforta;

刪除用戶

DROP USER bforta;

設(shè)置訪問權(quán)限

新創(chuàng)建的用戶沒有任何權(quán)限窖逗,只能登錄服務(wù)器,不能操作任何表和數(shù)據(jù)庫餐蔬。

查看權(quán)限:

SHOW GRANTS FOR bforta;

#輸出為
+-------------------------------------------------+
| Grants for bforta@%                             |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO 'bforta'@'%'              |
+-------------------------------------------------+

ON*.*表示在任意數(shù)據(jù)庫和任意表上對任何東西沒有權(quán)限碎紊。

另外,“MySQL的權(quán)限用用戶名和主機名結(jié)合定義樊诺,即user@host矮慕。如果不指定主機名,則使用默認(rèn)的主機名%(授予用戶訪問權(quán)限而不管主機名)啄骇。

可以使用 GRANT 語句授予用戶權(quán)限,

  • 要授予的權(quán)限瘟斜;
  • 被授予訪問權(quán)限的數(shù)據(jù)庫或表缸夹;
  • 用戶名。

以下例子給出GRANT的用法:

GRANT SELECT ON crashcourse.* TO beforta;

這條語句授予beforta用戶對crashcourse數(shù)據(jù)庫中所有的表上使用SELECT語句的權(quán)限螺句。

可以使用REVOKE語句來撤銷GRANT授予的權(quán)限:

REVOKE SELECT ON crashcourse.* FROM beforta

GRANT和REVOKE可在幾個層次上控制訪問權(quán)限:

  • 整個服務(wù)器虽惭,使用GRANT ALL和REVOKE ALL;
  • 整個數(shù)據(jù)庫蛇尚,使用ON database.*芽唇;
  • 特定的表,使用ON database.table;
  • 特定的列匆笤;
  • 特定的存儲過程研侣。

以下是具體權(quán)限內(nèi)容:

WX20200620-145326@2x.png

可通過列出各權(quán)限并用逗號分隔,將多條GRANT語句串在一起炮捧,如下所示:

GRANT SELECT, INSERT ON crashcourse.* TO beforta;

更改口令

可以使用下列語句更改口令:

SET PASSWORD FOR bforta = Password('n3w p@$$w0rd');

新口令必須傳遞到Password()函數(shù)進行加密庶诡。

Ch 29.數(shù)據(jù)庫維護

1.備份數(shù)據(jù)

對數(shù)據(jù)庫進行備份主要有以下幾種方式:

  • 在MySQL命令行使用mysqldump將所有數(shù)據(jù)庫內(nèi)容存儲到某個外部文件中;
  • 在MySQL命令行使用mysqlhotcopy從一個數(shù)據(jù)庫復(fù)制所有數(shù)據(jù)(并非所有的數(shù)據(jù)庫引擎都支持)咆课;
  • 可以使用MySQL的BACKUP TABLESELECT INTO OUTFILE轉(zhuǎn)儲所有數(shù)據(jù)到某個外部文件末誓。數(shù)據(jù)可以用RESTORE TABLE來復(fù)原。

注意:為了保證所有數(shù)據(jù)被寫到磁盤(包括索引數(shù)據(jù))书蚪,可能需要在進行備份前使用FLUSH TABLES語句喇澡。

2.進行數(shù)據(jù)庫維護

應(yīng)該知道以下語句:

ANALYZE TABLE,用來檢查表鍵是否正確殊校。ANALYZE TABLE返回如下所示的狀態(tài)信息:

ANALYZE TABLE orders;

CHECK TABLE用來針對許多問題對表進行檢查晴玖。CHECK TABLE支持一系列的用于MyISAM引擎表的方式。CHANGED檢查自最后一次檢查以來改動過的表箩艺。EXTENDED執(zhí)行最徹底的檢查窜醉,F(xiàn)AST只檢查未正常關(guān)閉的表,MEDIUM檢查所有被刪除的鏈接并進行鍵檢驗艺谆,QUICK只進行快速掃描榨惰。如下所示,CHECK TABLE發(fā)現(xiàn)和修復(fù)問題:

CHECK TABLE orders, orderitems;

3.診斷啟動問題

在排除系統(tǒng)啟動問題時静汤,首先應(yīng)該盡量用手動啟動服務(wù)器琅催。MySQL服務(wù)器自身通過在命令行上執(zhí)行mysqld啟動。下面是幾個重要的mysqld命令行選項:

  • --help顯示幫助——一個選項列表虫给;
  • --safe-mode裝載減去某些最佳配置的服務(wù)器藤抡;
  • --verbose顯示全文本消息(為獲得更詳細(xì)的幫助消息與--help聯(lián)合使用);
  • --version顯示版本信息然后退出抹估。

4.查看日志文件

MySQL維護管理員依賴的一系列日志文件缠黍。主要的日志文件有以下幾種:

  • 錯誤日志。它包含啟動和關(guān)閉問題以及任意關(guān)鍵錯誤的細(xì)節(jié)药蜻。此日志通常名為hostname.err瓷式,位于data目錄中。此日志名可用--log-error命令行選項更改语泽。
  • 查詢?nèi)罩久车洹K涗浰蠱ySQL活動,在診斷問題時非常有用踱卵。此日志文件可能會很快地變得非常大廊驼,因此不應(yīng)該長期使用它。此日志通常名為hostname.log,位于data目錄中妒挎。此名字可以用--log命令行選項更改绳锅。
  • 二進制日志。它記錄更新過數(shù)據(jù)(或者可能更新過數(shù)據(jù))的所有語句饥漫。此日志通常名為hostname-bin榨呆,位于data目錄內(nèi)。此名字可以用--log-bin命令行選項更改庸队。注意积蜻,這個日志文件是MySQL 5中添加的,以前的MySQL版本中使用的是更新日志彻消。
  • 緩慢查詢?nèi)罩靖筒稹n櫭剂x,此日志記錄執(zhí)行緩慢的任何查詢宾尚。這個日志在確定數(shù)據(jù)庫何處需要優(yōu)化很有用丙笋。此日志通常名為hostname-slow.log,位于data目錄中煌贴。此名字可以用--log-slow-queries命令行選項更改御板。

Ch 30.改善性能

數(shù)據(jù)庫管理員把他們生命中的相當(dāng)一部份時間花在了調(diào)整、試驗以改善DBMS性能之上牛郑。在診斷應(yīng)用的滯緩現(xiàn)象和性能問題時怠肋,性能不良的數(shù)據(jù)庫(以及數(shù)據(jù)庫查詢)通常是最常見的禍因。

回顧之前的章節(jié)淹朋,總結(jié)了一下的幾個性能Tips:

  • 首先笙各,MySQL(與所有DBMS一樣)具有特定的硬件建議。在學(xué)習(xí)和研究MySQL時础芍,使用任何舊的計算機作為服務(wù)器都可以杈抢。但對用于生產(chǎn)的服務(wù)器來說,應(yīng)該堅持遵循這些硬件建議仑性。
  • 一般來說惶楼,關(guān)鍵的生產(chǎn)DBMS應(yīng)該運行在自己的專用服務(wù)器上。
  • MySQL是用一系列的默認(rèn)設(shè)置預(yù)先配置的诊杆,從這些設(shè)置開始通常是很好的鲫懒。但過一段時間后你可能需要調(diào)整內(nèi)存分配、緩沖區(qū)大小等刽辙。(為查看當(dāng)前設(shè)置,可使用SHOW VARIABLES;和SHOW STATUS;甲献。)
  • MySQL是一個多用戶多線程的DBMS宰缤,換言之,它經(jīng)常同時執(zhí)行多個任務(wù)。如果這些任務(wù)中的某一個執(zhí)行緩慢慨灭,則所有請求都會執(zhí)行緩慢朦乏。如果你遇到顯著的性能不良,可使用SHOW PROCESS LIST顯示所有活動進程(以及它們的線程ID和執(zhí)行時間)氧骤。你還可以用KILL命令終結(jié)某個特定的進程(使用這個命令需要作為管理員登錄)呻疹。
  • 總是有不止一種方法編寫同一條SELECT語句。應(yīng)該試驗聯(lián)結(jié)筹陵、并刽锤、子查詢等,找出最佳的方法朦佩。
  • 使用EXPLAIN語句讓MySQL解釋它將如何執(zhí)行一條SELECT語句并思。
  • 一般來說,存儲過程執(zhí)行得比一條一條地執(zhí)行其中的各條MySQL語句快语稠。
  • 應(yīng)該總是使用正確的數(shù)據(jù)類型宋彼。
  • 決不要檢索比需求還要多的數(shù)據(jù)。換言之仙畦,不要用SELECT*(除非你真正需要每個列)输涕。
  • 有的操作(包括INSERT)支持一個可選的DELAYED關(guān)鍵字,如果使用它慨畸,將把控制立即返回給調(diào)用程序莱坎,并且一旦有可能就實際執(zhí)行該操作。
  • 在導(dǎo)入數(shù)據(jù)時先口,應(yīng)該關(guān)閉自動提交型奥。你可能還想刪除索引(包括FULLTEXT索引),然后在導(dǎo)入完成后再重建它們碉京。
  • 必須索引數(shù)據(jù)庫表以改善數(shù)據(jù)檢索的性能厢汹。確定索引什么不是一件微不足道的任務(wù),需要分析使用的SELECT語句以找出重復(fù)的WHERE和ORDER BY子句谐宙。如果一個簡單的WHERE子句返回結(jié)果所花的時間太長烫葬,則可以斷定其中使用的列(或幾個列)就是需要索引的對象。
  • 你的SELECT語句中有一系列復(fù)雜的OR條件嗎凡蜻?通過使用多條SELECT語句和連接它們的UNION語句搭综,你能看到極大的性能改進。
  • 索引改善數(shù)據(jù)檢索的性能划栓,但損害數(shù)據(jù)插入兑巾、刪除和更新的性能。如果你有一些表忠荞,它們收集數(shù)據(jù)且不經(jīng)常被搜索蒋歌,則在有必要之前不要索引它們帅掘。(索引可根據(jù)需要添加和刪除。)
  • LIKE很慢堂油。一般來說修档,最好是使用FULLTEXT而不是LIKE。
  • 數(shù)據(jù)庫是不斷變化的實體府框。一組優(yōu)化良好的表一會兒后可能就面目全非了吱窝。由于表的使用和內(nèi)容的更改,理想的優(yōu)化和配置也會改變迫靖。
  • 最重要的規(guī)則就是院峡,每條規(guī)則在某些條件下都會被打破。

以上差不多就是《MySQL 必知必會》這本書的全部內(nèi)容了袜香,這本書深入淺出對MySQL數(shù)據(jù)庫進行了一個整體的介紹撕予。但是我們的高性能SQL的計劃才剛剛開始。

未完待續(xù)······

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜈首,一起剝皮案震驚了整個濱河市实抡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欢策,老刑警劉巖吆寨,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異踩寇,居然都是意外死亡啄清,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門俺孙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辣卒,“玉大人,你說我怎么就攤上這事睛榄∪倜#” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵场靴,是天一觀的道長啡莉。 經(jīng)常有香客問我,道長旨剥,這世上最難降的妖魔是什么咧欣? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮轨帜,結(jié)果婚禮上魄咕,老公的妹妹穿的比我還像新娘。我一直安慰自己蚌父,他們只是感情好蚕礼,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布烟具。 她就那樣靜靜地躺著,像睡著了一般奠蹬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗡午,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天囤躁,我揣著相機與錄音,去河邊找鬼荔睹。 笑死狸演,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僻他。 我是一名探鬼主播宵距,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吨拗!你這毒婦竟也來了满哪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤劝篷,失蹤者是張志新(化名)和其女友劉穎哨鸭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娇妓,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡像鸡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哈恰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片只估。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖着绷,靈堂內(nèi)的尸體忽然破棺而出蛔钙,到底是詐尸還是另有隱情,我是刑警寧澤蓬戚,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布夸楣,位于F島的核電站,受9級特大地震影響子漩,放射性物質(zhì)發(fā)生泄漏豫喧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一幢泼、第九天 我趴在偏房一處隱蔽的房頂上張望紧显。 院中可真熱鬧,春花似錦缕棵、人聲如沸孵班。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篙程。三九已至枷畏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虱饿,已是汗流浹背拥诡。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氮发,地道東北人渴肉。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像爽冕,于是被迫代替她去往敵國和親仇祭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 一颈畸、MySQL架構(gòu)與歷史 A.并發(fā)控制 1.共享鎖(shared lock乌奇,讀鎖):共享的,相互不阻塞的 2.排他...
    ZyBlog閱讀 19,830評論 3 177
  • 全書的重點在四五六章:如何建表承冰、如何建索引华弓、如何查詢。第一章講解了一些基本概念:鎖與事物隔離 重中之重:4.1數(shù)據(jù)...
    AbrahamW閱讀 983評論 0 0
  • 今天計劃繼續(xù)困乒,主要內(nèi)容是《MySQL必知必會》19-22章的內(nèi)容寂屏。 Ch 19.插入數(shù)據(jù) 1.插入一行 使用第二種...
    劉點石閱讀 313評論 0 0
  • 一、分區(qū)表 分區(qū)表用于把相關(guān)數(shù)據(jù)放在一起娜搂,以分區(qū)為單位進行批量刪除迁霎,檢查/修復(fù),備份/恢復(fù)等數(shù)據(jù)操作百宇。當(dāng)數(shù)據(jù)表非常...
    陳菲TW閱讀 161評論 0 1
  • 1.鎖有兩種類型:讀鎖和寫鎖考廉。讀鎖是共享的,或者說是相互不阻塞的携御,多個客戶在同一時刻可以同時讀取同一資源昌粤,而互不干...
    奔跑的Robi閱讀 304評論 0 0