1. 程式人生 > >MySQL - - 【檢視】【觸發器】【儲存過程】【函式】【事物】【資料庫鎖】【資料庫備份】

MySQL - - 【檢視】【觸發器】【儲存過程】【函式】【事物】【資料庫鎖】【資料庫備份】

目錄

  • 檢視
  • 觸發器
  • 儲存過程
  • 函式
  • 事物
  • 資料庫鎖
  • 資料庫備份

1 檢視

  • 檢視:是一個虛擬表,其內容由查詢定義。同真實的表一樣,檢視包含一系列帶有名稱的列和行資料
  • 檢視有如下特點;
    • 1 檢視的列可以來自不同的表,是表的抽象和邏輯意義上建立的新關係。
    • 2 檢視是由基本表(實表)產生的表(虛表)。
    • 3 檢視的建立和刪除不影響基本表。
    • 4 對檢視內容的更新(新增、刪除和修改)直接影響基本表。
    • 5 當檢視來自多個基本表時,不允許新增和刪除資料。
  • 1 建立檢視
create view 檢視名稱  as sql 查詢語句  
  • 2 使用檢視
select * from 檢視名稱;
  • 3 更新檢視
alter view 檢視名稱 AS SQL語句
  • 4 刪除檢視
drop view ren_view;

2 觸發器

  • 觸發器:監視某種情況,並觸發某種操作。
  • 觸發器建立語法四要素:
    • 1 監視地點(table)
    • 2 監視事件(insert/update/delete)
    • 3 觸發時間(after/before)
    • 4 觸發事件(insert/update/delete)
  • 建立觸發器語法
create trigger triggerName  after/before  insert/update/delete
     on 表名 for each row #這句話是固定的
 begin
     #需要執行的sql語句
 end
注意1:after/before: 只能選一個 ,after 表示 後置觸發, before 表示前置觸發
注意2:insert/update/delete:只能選一個
  • 建立兩張表

#商品表

create table goods(

  id int primary key auto_increment,

  name varchar(20),

  num int

);

#訂單表

create table order_table(

    oid int primary key auto_increment,

    gid int,

    much int

);
  • 新增3條商品資料
insert into goods(name,num) values('商品1',10),('商品2',10),('商品3',10);
  • 如果我們在沒使用觸發器之前:假設我們現在賣了3個商品1,我們需要做兩件事
    • 1 往訂單表插入一條記錄
insert into order_table(gid,much) values(1,3);
- 2 更新商品表商品1的剩餘數量
update goods set num=num-3 where id=1;
  • 建立一個觸發器:
create trigger tg1 after insert on  order_table
for each row
begin    
  update goods set num = num -3 where id = 1;
end
  • 執行
insert into order_table(gid,much) values(1,3);
  • 會發現商品1的數量變為7了,說明在我們插入一條訂單的時候,
  • 觸發器自動幫我們做了更新操作。
  • 但現在會有一個問題,因為我們觸發器裡面num和id都是寫死的,所以不管我們買哪個商品,最終更新的都是商品1的數量。比如:我們往訂單表再插入一條記錄:
insert into order_table(gid,much) values(2,3);
  • 執行完後會發現商品1的數量變4了,而商品2的數量沒變,這樣顯然不是我們想要的結果。我們需要改改我們之前建立的觸發器。
  • 我們如何在觸發器引用行的值,也就是說我們要得到我們新插入的訂單記錄中的gid或much的值。
  • 對於insert而言,新插入的行用new來表示,行中的每一列的值用new.列名來表示。
  • 所以現在我們可以這樣來改我們的觸發器:
create trigger tg2 after insert on order_table
for each row
begin
 update goods set num = num-new.much  where id = new.gid;
end
  • 第二個觸發器建立完畢,我們先把第一個觸發器刪掉
drop trigger tg1;
  • 再來測試一下,插入一條訂單記錄:
insert into order_table(gid,much) values(2,3)
  • 執行完發現商品2的數量變為7了,現在就對了。

  • 現在還存在兩種情況:
  • 1 當用戶撤銷一個訂單的時候,我們這邊直接刪除一個訂單,我們是不是需要把對應的商品數量再加回去呢?
  • 對於delete而言:原本有一行,後來被刪除,想引用被刪除的這一行,用old來表示舊錶中的值,old.列名可以引用原(舊)表中的值。
  • 那我們的觸發器就該這樣寫:

create trigger tg3 afert delete  on order_table
for each row
bigen
    update goods set num = num + old.much where id = old.gid;-- (注意這邊的變化)
end
  • 2 當用戶修改一個訂單的數量時,我們觸發器修改怎麼寫?
create trigger tg4 after update on order_table
for each row
begin
    update goods set num = num+old.much-new.much where id = old.gid;
end

3 儲存過程

  • MySQL資料庫在5.0版本後開始支援儲存過程,那麼什麼是儲存過程呢?怎麼建立、檢視和刪除儲存過程呢?儲存過程有什麼優點?
  • 儲存過程:類似於函式(方法),簡單的說儲存過程是為了完成某個資料庫中的特定功能而編寫的語句集合,該語句集包括SQL語句(對資料的增刪改查)、條件語句和迴圈語句等。

  • 1 檢視現有的儲存過程

show procedure status;
  • 2 刪除儲存過程
drop procedure 儲存過程名稱;
  • 3 呼叫 儲存過程
call 儲存過程名稱(引數入/出型別 引數名 資料型別);
  • 4 建立儲存過程

  • 體會封裝

#1.體會封裝
create procedure p1 ()
begin
    select * from account;  
end
  • SQL 體會引數
create procedure p2(in i int,out n varchar(50))
begin
 select name into n from account where id = i;
end
 
-- 呼叫
set @name =null;
CALL p2(1,@name);
select @name;
  • 注意1: mysql中有三種出入引數型別:分別為:1. in 入參型別 2.out 出參型別 3. inout 出入參型別
  • 注意2: into 關鍵字 可以 將前面欄位的查詢結果 執行 給 into 後面的變數.

  • in入參示例

-- 建立儲存過程 in 入參
create procedure p_in (IN num int )
begin
    select num;
    set num=100;
    select num;
end;

-- 呼叫
set @num=1;
call p_in(@num);
select @num;
-- 總結: IN 引數只是將變數在儲存過程內部做了修改,並沒有影響到外部,@num仍為1。
  • out出參示例
-- 建立儲存過程 out 出參
create procedure p_out (out num int )
begin
    select num;
    set num=100;
    select num;
end;

-- 呼叫
set @num=1;
call p_out(@num);
select @num;
  • inout出入參示例
-- 建立儲存過程 inout 出入參
create procedure p_inout (inout num int )
begin
    select num;
    set num=100;
    select num;
end;

-- 呼叫
set @num=1;
call p_inout(@num);
select @num;
  • SQL 體會控制
#3.SQL 體會控制
 create procedure p3(in x int,in c char(1))
 begin
    if c ='d' then
         select * from account where money >x;
   else
         select * from account where money <x;     
  end if;
end
  • 體會迴圈:計算1-100累加的和,並且返回計算結果.
#4.體會迴圈:計算1-100累加的和,並且返回計算結果.
create procedure p4(inout n int)
begin
      DECLARE sum int default 0; -- 設定總和變數,並且指定初始值0
      declare i int; -- 宣告變數
      set i = 0;    -- 通過set為變數設定值
    while i<=n DO  -- 開始迴圈
            set sum = sum +i;
            set i = i+1;
      end while; -- 結束迴圈
 
    select sum; -- 提供結果
                     
     set n = sum;--將計算結果提供給 輸出變數 n;
end;
                 
 -- 呼叫:
 set @n = 100;
 call p4(@n);
 select @n;
  • 儲存過程優點:
    • 1、儲存過程增強了SQL語言靈活性。
      • 儲存過程可以使用控制語句編寫,可以完成複雜的判斷和較複雜的運算,有很強的靈活性;
    • 2、減少網路流量,降低了網路負載。
      • 儲存過程在伺服器端建立成功後,只需要呼叫該儲存過程即可,而傳統的做法是每次都將大量的SQL語句通過網路傳送至資料庫伺服器端然後再執行
    • 3、儲存過程只在創造時進行編譯,以後每次執行儲存過程都不需再重新編譯。
      • 一般SQL語句每執行一次就編譯一次,所以使用儲存過程可提高資料庫執行速度。
  • 儲存過程缺點:
    • 1、擴充套件功能不方便
    • 2、不便於系統後期維護

4 函式

  • MySQL提供的內建函式:
一、數學函式
    ROUND(x,y)
        返回引數x的四捨五入的有y位小數的值
        
    RAND()
        返回0到1內的隨機值,可以通過提供一個引數(種子)使RAND()隨機數生成器生成一個指定的值。

二、聚合函式(常用於GROUP BY從句的SELECT查詢中)
    AVG(col)返回指定列的平均值
    COUNT(col)返回指定列中非NULL值的個數
    MIN(col)返回指定列的最小值
    MAX(col)返回指定列的最大值
    SUM(col)返回指定列的所有值之和
    GROUP_CONCAT(col) 返回由屬於一組的列值連線組合而成的結果    
    
三、字串函式

    CHAR_LENGTH(str)
        返回值為字串str 的長度,長度的單位為字元。一個多位元組字元算作一個單字元。
    CONCAT(str1,str2,...)
        字串拼接
        如有任何一個引數為NULL ,則返回值為 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字串拼接(自定義連線符)
        CONCAT_WS()不會忽略任何空字串。 (然而會忽略所有的 NULL)。

    FORMAT(X,D)
        將數字X 的格式寫為'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字串的形式返回。若  D 為 0, 則返回結果不帶有小數點,或不含小數部分。
        例如:
            SELECT FORMAT(12332.1,4); 結果為: '12,332.1000'
    
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字串
            pos:要替換位置其實位置
            len:替換的長度
            newstr:新字串
        例如:
            SELECT INSERT('abcd',1,2,'tt'); 結果為: 'ttcd'
            SELECT INSERT('abcd',1,4,'tt'); 結果為: 'tt'
        特別的:
            如果pos超過原字串長度,則返回原字串
            如果len超過原字串長度,則由新字串完全替換
    
    INSTR(str,substr)
        返回字串 str 中子字串的第一個出現位置。

    LEFT(str,len)
        返回字串str 從開始的len位置的子序列字元。
        例如:
            SELECT INSTR('abc','c'); 結果為: 3
            SELECT INSTR('abc','d'); 結果為: 0
            
    LOWER(str)
        變小寫

    UPPER(str)
        變大寫
   
    REVERSE(str)
        返回字串 str ,順序和字元順序相反。
        例如:
            SELECT REVERSE('1234567') 結果為:7654321
            
    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不帶有len 引數的格式從字串str返回一個子字串,起始於位置 pos。帶有len引數的格式從字串str返回一個長度同len字元相同的子字串,起始於位置 pos。 使用 FROM的格式為標準 SQL 語法。也可能對pos使用一個負值。假若這樣,則子字串的位置起始於字串結尾的pos 字元,而不是字串的開頭位置。在以下格式的函式中可以對pos 使用一個負值。

        mysql> SELECT SUBSTRING('Quadratically',5); -- 從第5位開始擷取
            -> 'ratically'

        mysql> SELECT SUBSTRING('foobarbar' FROM 4); -- 從第4位開始擷取
            -> 'barbar'

        mysql> SELECT SUBSTRING('Quadratically',5,6); --從第5位開始擷取,擷取6個長度
            -> 'ratica'

        mysql> SELECT SUBSTRING('Sakila', -3);    -- 從倒數第3位開始擷取
            -> 'ila'

        mysql> SELECT SUBSTRING('Sakila', -5, 3); -- 從倒數第5位開始擷取,擷取3個長度
            -> 'aki'
            
四、日期和時間函式
    CURDATE()或CURRENT_DATE() 返回當前的日期
    CURTIME()或CURRENT_TIME() 返回當前的時間
    DAYOFWEEK(date)   返回date所代表的一星期中的第幾天(1~7)
    DAYOFMONTH(date)  返回date是一個月的第幾天(1~31)
    DAYOFYEAR(date)   返回date是一年的第幾天(1~366)
    DAYNAME(date)   返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE);
    FROM_UNIXTIME(ts,fmt)  根據指定的fmt格式,格式化UNIX時間戳ts
    HOUR(time)   返回time的小時值(0~23)
    MINUTE(time)   返回time的分鐘值(0~59)
    MONTH(date)   返回date的月份值(1~12)
    MONTHNAME(date)   返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE);
    NOW()    返回當前的日期和時間
    QUARTER(date)   返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE);
    WEEK(date)   返回日期date為一年中第幾周(0~53)
    YEAR(date)   返回日期date的年份(1000~9999)
    
    重點:
    DATE_FORMAT(date,format) 根據format字串格式化date值

       mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');
        -> 'Sunday October 2009'
       mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
       mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00',
        ->                 '%D %y %a %d %m %b %j');
        -> '4th 00 Thu 04 10 Oct 277'
       mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
        ->                 '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
       mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
       mysql> SELECT DATE_FORMAT('2006-06-00', '%d');
        -> '00'
        
五、加密函式
    MD5()    
        計算字串str的MD5校驗和
        例如:
            SELECT MD5('1234') 結果為:81dc9bdb52d04dc20036dbd8313ed055
    PASSWORD(str)   
        返回字串str的加密版本,這個加密過程是不可逆轉的
        例如:
            SELECT PASSWORD('1234') 結果為:*A4B6157319038724E3560894F7F932C8886EBFCF
        
六、控制流函式            
    CASE WHEN[test1] THEN [result1]...ELSE [default] END
        如果testN是真,則返回resultN,否則返回default
    CASE [test] WHEN[val1] THEN [result]...ELSE [default]END  
        如果test和valN相等,則返回resultN,否則返回default

    IF(test,t,f)   
        如果test是真,返回t;否則返回f

    IFNULL(arg1,arg2) 
        如果arg1不是空,返回arg1,否則返回arg2
        例如:
            SELECT IFNULL('bbb','abc'); 結果為: bbb
            SELECT IFNULL(null,'abc');  結果為: abc

    NULLIF(arg1,arg2) 
        如果arg1=arg2返回NULL;否則返回arg1
        例如:
            SELECT NULLIF('bbb','bbb');結果為: null
            SELECT NULLIF('aaa','bbb');結果為: aaa
  • 更多內建函式:https://dev.mysql.com/doc/refman/5.7/en/functions.html

  • 1 自定義函式

CREATE FUNCTION fun1(i1 int,i2 int)
 
RETURNS INT //設定返回型別
 
BEGIN
    DECLARE sum int default 0;
    set sum = i1+i2;
    RETURN(sum); //返回結果
end
  • 2 呼叫自定義函式
#直接呼叫自定義函式
select fun1(1,5);
 
#在sql語句中使用自定義函式
select fun1(引數1,引數2),name from 表名
  • 3 刪除自定義函式
DROP FUNCTION fun_name;
  • 4 函式與儲存過程的區別:
函式 過程
一般用於計算資料 完成特定的任務
宣告為FUNCTION 宣告為PROCEDURE
需要描述型別,且PL/SQL 塊中至少有一個有效的 RETURN 語句 無返回型別,可通過OUT、IN OUT 引數返回多個值
不能獨立執行,必須作為表示式一部分 可作為一個獨立的 PL/SQL 語句執行
在 DML和DQL中可呼叫函式 在DML和DQL中不可呼叫過程

5 事物

5.1 什麼是事務

  • 一組sql語句批量執行,要麼全部執行成功,要麼全部執行失敗

5.2 為什麼出現這種技術

  • 為什麼要使用事務這個技術呢? 現在的很多軟體都是多使用者,多程式,多執行緒的,對同一個表可能同時有很多人在用,為保持資料的一致性,所以提出了事務的概念。這樣很抽象,舉個例子:
  • A 給B 要劃錢,A 的賬戶-1000元, B 的賬戶就要+1000元,這兩個update 語句必須作為一個整體來執行,不然A 扣錢了,B 沒有加錢這種情況很難處理。

5.3 事物的特性 

  • 80年代中國人結婚四大件:手錶、自行車、縫紉機、收音機(三轉一響)。要把事務娶回家同樣需要四大件,所以事務很刻薄(ACID),四大件清單:原子性(Atom)、一致性(Consistent)、隔離性(Isolate)、永續性(Durable)。ACID就是資料庫事務正確執行的四個特性的縮寫。
    • 原子性:要麼不談,要談就要結婚!
      • 對於其資料修改,要麼全都執行,要麼全都不執行。
    • 一致性:戀愛時,什麼方式愛我;結婚後還得什麼方式愛我;
      • 資料庫原來有什麼樣的約束,事務執行之後還需要存在這樣的約束,所有規則都必須應用於事務的修改,以保持所有資料的完整性。
    • 隔離性:鬧完洞房後,是倆人的私事。
      • 一個事務不能知道另外一個事務的執行情況(中間狀態)
    • 永續性:一旦領了結婚證,無法後悔。
      • 即使出現致命的系統故障也將一直保持。不要告訴我係統說commit成功了,回頭電話告訴我,伺服器機房斷電了,我的事務涉及到的資料修改可能沒有進入資料庫。
  • 另外需要注意:
    • 在 MySQL 中只有使用了 Innodb 資料庫引擎的資料庫或表才支援事務。
    • 事務處理可以用來維護資料庫的完整性,保證成批的 SQL 語句要麼全部執行,要麼全部不執行。
    • 事務用來管理 insert,update,delete 語句

5.4 事務控制語句

  • BEGIN 或 START TRANSACTION;顯式地開啟一個事務;
  • COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會提交事務,並使已對資料庫進行的所有修改稱為永久性的;
  • ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。回滾會結束使用者的事務,並撤銷正在進行的所有未提交的修改;
  • SAVEPOINT : 儲存點,可以把一個事物分割成幾部分.在執行ROLLBACK 時 可以指定在什麼位置上進行回滾操作.
  • 注意: SET AUTOCOMMIT=0 ;禁止自動提交 和 SET AUTOCOMMIT=1 開啟自動提交.

5.5 例子: 魯班轉賬給后羿

  • 1 建立表
create table account(
    id int(50) not null auto_increment primary key,
    name VARCHAR(50) not null,
    money DOUBLE(10,2) not NULL
);
  • 2 插入資料
insert into account (id,name,money) values(1,'魯班',250),(2,'后羿',5000);
  • 3 執行轉賬
start transaction; -- 開啟事物
 --  執行sql語句操作
 update account set money = money - 500 where id =1;  
 update account set money = money+500 where id = 2;
 
commit;  -- 手動提交事物
rollback; -- 回滾事物
 
--  檢視結果
select * from account;
  • 4 儲存點使用
START TRANSACTION ;
 
insert into account (name,money) values('李元芳',1000);
 
SAVEPOINT s1; -- 設定儲存點
 
insert into account (name,money) values('張桂枝',1500);
 
ROLLBACK to s1; -- 事物回滾到儲存點<br>COMMIT; --提交事物

6 資料庫鎖

  • 需求: 有一個賬戶,兩個人在同一時間要對此賬戶操作,A要對賬戶充值100塊,B要從賬戶中取出100塊.操作前都要先看一下賬戶的 餘額然後再操作.
-- 視窗1 使用者進行充值

-- 充值前 先檢視餘額
set @m=0;

SELECT money into @m from account where id = 1;

select @m;

-- 看到餘額後 充值100 塊
update account set money = @m + 100 where id = 1;

SELECT * from account;

--------------------------------------------------------------
-- 視窗2 使用者進行取款

-- 取款前 先檢視餘額
set @m=0;

SELECT money into @m from account where id = 1;

select @m;

-- 看到餘額後 取款100 塊
update account set money = @m - 100 where id = 1;

SELECT * from account;

6.1 鎖的基本概念

  • 當併發事務同時訪問一個資源時,有可能導致資料不一致,因此需要一種機制來將資料訪問順序化,以保證資料庫資料的一致性。

6.2 鎖的基本型別

  • 多個事務同時讀取一個物件的時候,是不會有衝突的。同時讀和寫,或者同時寫才會產生衝突。因此為了提高資料庫的併發效能,通常會定義兩種鎖:共享鎖和排它鎖。
  • 1 共享鎖(Shared Lock,也叫S鎖)
    • 共享鎖(S)表示對資料進行讀操作。因此多個事務可以同時為一個物件加共享鎖。(如果試衣間的門還沒被鎖上,顧客都能夠同時進去參觀)
  • 2 排他鎖(Exclusive Lock,也叫X鎖)
    • 排他鎖(X)表示對資料進行寫操作。如果一個事務對 物件加了排他鎖,其他事務就不能再給它加任何鎖了。(某個顧客把試衣間從裡面反鎖了,其他顧客想要使用這個試衣間,就只有等待鎖從裡面給打開了).

6.3 實際開發中常見的兩種鎖:

  • 1 悲觀鎖 顧名思義
    • 就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block(阻塞)直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制.
  • 注意:要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性.因為MySQL預設使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。關閉自動提交命令為:set autocommit=0;
  • 設定完autocommit後,我們就可以執行我們的正常業務了。具體如下:
-- 0.開始事務
start transaction;
 
-- 1.查詢賬戶餘額
set @m = 0; -- 賬戶餘額
select money into @m from account where id = 1 for update;
select @m;
 
-- 2.修改賬戶餘額
update account set money = @m -100 where id = 1;
 
select * FROM account where id = 1;
-- 3. 提交事務
commit;
  • 在另外的查詢頁面執行:
-- 0.開始事務
start transaction;
 
-- 1.查詢賬戶餘額
set @m = 0; -- 賬戶餘額
select money into @m from account where id = 1 for update;
select @m;
 
-- 2.修改賬戶餘額
update account set money = @m +100 where id = 1;
 
select * FROM account where id = 1;
-- 3. 提交事務
commit;
  • 會發現當前查詢會進入到等待狀態,不會顯示出資料,當上面的sql執行完畢提交事物後,當前sql才會顯示結果.
  • 注意1:在使用悲觀鎖時,如果表中沒有指定主鍵,則會進行鎖表操作.
  • 注意2: 悲觀鎖的確保了資料的安全性,在資料被操作的時候鎖定資料不被訪問,但是這樣會帶來很大的效能問題。因此悲觀鎖在實際開發中使用是相對比較少的。 

  • 2 樂觀鎖, 顧名思義
    • 就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。 
  • 使用樂觀鎖的兩種方式:
    • 1 使用資料版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現 方式。何謂資料版本?即為資料增加一個版本標識,一般是通過為資料庫表增加一個數字型別的 “version” 欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷資料庫表對應記錄 的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數 據。
-- 1.查詢賬戶餘額
set @m = 0; -- 賬戶餘額
select money into @m from account where id = 1 ;
select @m;
-- 2.查詢版本號
set @version = 0; -- 版本號
select version into @version from account where id = 1 ;
select @version;
 
-- 3.修改賬戶餘額
update account set money = @m -100,version=version+1 where id = 1 and version = @version;
 
select * FROM account where id = 1;
- 2 樂觀鎖定的第二種實現方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加一個欄位,名稱無所謂,欄位型別使用時間戳 (datatime), 和上面的version類似,也是在更新提交的時候檢查當前資料庫中資料的時間戳和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本衝突。
  • 悲觀鎖與樂觀鎖的優缺點:
  • 兩種鎖各有其有點缺點,不能單純的講哪個更好.
    • 樂觀鎖適用於寫入比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。
    • 但如果經常產生衝突,上層應用會不斷的進行重試操作,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適.

7 資料庫備份

  • mysqldump 命令將資料庫中的資料備份成一個文字檔案。表的結構和表中的資料將儲存在生成的文字檔案中。
  • mysqldump命令的工作原理很簡單。它先查出需要備份的表的結構,再在文字檔案中生成一個CREATE語句。然後,將表中的所有記錄轉換成一條INSERT語句。然後通過這些語句,就能夠建立表並插入資料。

  • 1 使用mysqldump實現邏輯備份

#語法:
# mysqldump -h 伺服器 -u使用者名稱 -p密碼 資料庫名 > 備份檔案.sql
 
#示例:
#單庫備份
mysqldump -uroot -p123456 db1 > c:/db1.sql
mysqldump -uroot -p123456 db1 table1 table2 > c:/db1-table1-table2.sql
 
#多庫備份
mysqldump -uroot -p123456 --databases db1 db2 mysql db3 > c:/db1_db2_mysql_db3.sql
 
#備份所有庫
mysqldump -uroot -p123456 --all-databases > c:/all.sql
  • 引數說明
--all-databases  , -A
匯出全部資料庫。
mysqldump  -uroot -p --all-databases
--all-tablespaces  , -Y
匯出全部表空間。
mysqldump  -uroot -p --all-databases --all-tablespaces
--no-tablespaces  , -y
不匯出任何表空間資訊。
mysqldump  -uroot -p --all-databases --no-tablespaces
--add-drop-database
每個資料庫建立之前新增drop資料庫語句。
mysqldump  -uroot -p --all-databases --add-drop-database
--add-drop-table
每個資料表建立之前新增drop資料表語句。(預設為開啟狀態,使用--skip-add-drop-table取消選項)
mysqldump  -uroot -p --all-databases  (預設新增drop語句)
mysqldump  -uroot -p --all-databases –skip-add-drop-table  (取消drop語句)
--add-locks
在每個表匯出之前增加LOCK TABLES並且之後UNLOCK  TABLE。(預設為開啟狀態,使用--skip-add-locks取消選項)
mysqldump  -uroot -p --all-databases  (預設新增LOCK語句)
mysqldump  -uroot -p --all-databases –skip-add-locks   (取消LOCK語句)
--allow-keywords
允許建立是關鍵詞的列名字。這由表名字首於每個列名做到。
mysqldump  -uroot -p --all-databases --allow-keywords
--apply-slave-statements
在'CHANGE MASTER'前新增'STOP SLAVE',並且在匯出的最後新增'START SLAVE'。
mysqldump  -uroot -p --all-databases --apply-slave-statements
--character-sets-dir
字符集檔案的目錄
mysqldump  -uroot -p --all-databases  --character-sets-dir=/usr/local/mysql/share/mysql/charsets
--comments
附加註釋資訊。預設為開啟,可以用--skip-comments取消
mysqldump  -uroot -p --all-databases  (預設記錄註釋)
mysqldump  -uroot -p --all-databases --skip-comments   (取消註釋)
--compatible
匯出的資料將和其它資料庫或舊版本的MySQL 相相容。值可以為ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_tables_options、no_field_options等,
要使用幾個值,用逗號將它們隔開。它並不保證能完全相容,而是儘量相容。
mysqldump  -uroot -p --all-databases --compatible=ansi
--compact
匯出更少的輸出資訊(用於除錯)。去掉註釋和頭尾等結構。可以使用選項:--skip-add-drop-table  --skip-add-locks --skip-comments --skip-disable-keys
mysqldump  -uroot -p --all-databases --compact
--complete-insert,  -c
使用完整的insert語句(包含列名稱)。這麼做能提高插入效率,但是可能會受到max_allowed_packet引數的影響而導致插入失敗。
mysqldump  -uroot -p --all-databases --complete-insert
--compress, -C
在客戶端和伺服器之間啟用壓縮傳遞所有資訊
mysqldump  -uroot -p --all-databases --compress
--create-options,  -a
在CREATE TABLE語句中包括所有MySQL特性選項。(預設為開啟狀態)
mysqldump  -uroot -p --all-databases
--databases,  -B
匯出幾個資料庫。引數後面所有名字參量都被看作資料庫名。
mysqldump  -uroot -p --databases test mysql
--debug
輸出debug資訊,用於除錯。預設值為:d:t,/tmp/mysqldump.trace
mysqldump  -uroot -p --all-databases --debug
mysqldump  -uroot -p --all-databases --debug=” d:t,/tmp/debug.trace”
--debug-check
檢查記憶體和開啟檔案使用說明並退出。
mysqldump  -uroot -p --all-databases --debug-check
--debug-info
輸出除錯資訊並退出
mysqldump  -uroot -p --all-databases --debug-info
--default-character-set
設定預設字符集,預設值為utf8
mysqldump  -uroot -p --all-databases --default-character-set=utf8
--delayed-insert
採用延時插入方式(INSERT DELAYED)匯出資料
mysqldump  -uroot -p --all-databases --delayed-insert
--delete-master-logs
master備份後刪除日誌. 這個引數將自動啟用--master-data。
mysqldump  -uroot -p --all-databases --delete-master-logs
--disable-keys
對於每個表,用/*!40000 ALTER TABLE tbl_name DISABLE KEYS */;和/*!40000 ALTER TABLE tbl_name ENABLE KEYS */;語句引用INSERT語句。這樣可以更快地匯入dump出來的檔案,因為它是在插入所有行後建立索引的。該選項只適合MyISAM表,預設為開啟狀態。
mysqldump  -uroot -p --all-databases 
--dump-slave
該選項將主的binlog位置和檔名追加到匯出資料的檔案中(show slave status)。設定為1時,將會以CHANGE MASTER命令輸出到資料檔案;設定為2時,會在change前加上註釋。該選項將會開啟--lock-all-tables,除非--single-transaction被指定。該選項會自動關閉--lock-tables選項。預設值為0。
mysqldump  -uroot -p --all-databases --dump-slave=1
mysqldump  -uroot -p --all-databases --dump-slave=2
--master-data
該選項將當前伺服器的binlog的位置和檔名追加到輸出檔案中(show master status)。如果為1,將會輸出CHANGE MASTER 命令;如果為2,輸出的CHANGE  MASTER命令前添加註釋資訊。該選項將開啟--lock-all-tables 選項,除非--single-transaction也被指定(在這種情況下,全域性讀鎖在開始匯出時獲得很短的時間;其他內容參考下面的--single-transaction選項)。該選項自動關閉--lock-tables選項。
mysqldump  -uroot -p --host=localhost --all-databases --master-data=1;
mysqldump  -uroot -p --host=localhost --all-databases --master-data=2;
--events, -E
匯出事件。
mysqldump  -uroot -p --all-databases --events
--extended-insert,  -e
使用具有多個VALUES列的INSERT語法。這樣使匯出檔案更小,並加速匯入時的速度。預設為開啟狀態,使用--skip-extended-insert取消選項。
mysqldump  -uroot -p --all-databases
mysqldump  -uroot -p --all-databases--skip-extended-insert   (取消選項)
--fields-terminated-by
匯出檔案中忽略給定欄位。與--tab選項一起使用,不能用於--databases和--all-databases選項
mysqldump  -uroot -p test test --tab=”/home/mysql” --fields-terminated-by=”#”
--fields-enclosed-by
輸出檔案中的各個欄位用給定字元包裹。與--tab選項一起使用,不能用於--databases和--all-databases選項
mysqldump  -uroot -p test test --tab=”/home/mysql” --fields-enclosed-by=”#”
--fields-optionally-enclosed-by
輸出檔案中的各個欄位用給定字元選擇性包裹。與--tab選項一起使用,不能用於--databases和--all-databases選項
mysqldump  -uroot -p test test --tab=”/home/mysql”  --fields-enclosed-by=”#” --fields-optionally-enclosed-by  =”#”
--fields-escaped-by
輸出檔案中的各個欄位忽略給定字元。與--tab選項一起使用,不能用於--databases和--all-databases選項
mysqldump  -uroot -p mysql user --tab=”/home/mysql” --fields-escaped-by=”#”
--flush-logs
開始匯出之前重新整理日誌。
請注意:假如一次匯出多個數據庫(使用選項--databases或者--all-databases),將會逐個資料庫重新整理日誌。除使用--lock-all-tables或者--master-data外。在這種情況下,日誌將會被重新整理一次,相應的所以表同時被鎖定。因此,如果打算同時匯出和重新整理日誌應該使用--lock-all-tables 或者--master-data 和--flush-logs。
mysqldump  -uroot -p --all-databases --flush-logs
--flush-privileges
在匯出mysql資料庫之後,發出一條FLUSH  PRIVILEGES 語句。為了正確恢復,該選項應該用於匯出mysql資料庫和依賴mysql資料庫資料的任何時候。
mysqldump  -uroot -p --all-databases --flush-privileges
--force
在匯出過程中忽略出現的SQL錯誤。
mysqldump  -uroot -p --all-databases --force
--help
顯示幫助資訊並退出。
mysqldump  --help
--hex-blob
使用十六進位制格式匯出二進位制字串欄位。如果有二進位制資料就必須使用該選項。影響到的欄位型別有BINARY、VARBINARY、BLOB。
mysqldump  -uroot -p --all-databases --hex-blob
--host, -h
需要匯出的主機資訊
mysqldump  -uroot -p --host=localhost --all-databases
--ignore-table
不匯出指定表。指定忽略多個表時,需要重複多次,每次一個表。每個表必須同時指定資料庫和表名。例如:--ignore-table=database.table1 --ignore-table=database.table2 ……
mysqldump  -uroot -p --host=localhost --all-databases --ignore-table=mysql.user
--include-master-host-port
在--dump-slave產生的'CHANGE  MASTER TO..'語句中增加'MASTER_HOST=<host>,MASTER_PORT=<port>'  
mysqldump  -uroot -p --host=localhost --all-databases --include-master-host-port
--insert-ignore
在插入行時使用INSERT IGNORE語句.
mysqldump  -uroot -p --host=localhost --all-databases --insert-ignore
--lines-terminated-by
輸出檔案的每行用給定字串劃分。與--tab選項一起使用,不能用於--databases和--all-databases選項。
mysqldump  -uroot -p --host=localhost test test --tab=”/tmp/mysql”  --lines-terminated-by=”##”
--lock-all-tables,  -x
提交請求鎖定所有資料庫中的所有表,以保證資料的一致性。這是一個全域性讀鎖,並且自動關閉--single-transaction 和--lock-tables 選項。
mysqldump  -uroot -p --host=localhost --all-databases --lock-all-tables
--lock-tables,  -l
開始匯出前,鎖定所有表。用READ  LOCAL鎖定表以允許MyISAM表並行插入。對於支援事務的表例如InnoDB和BDB,--single-transaction是一個更好的選擇,因為它根本不需要鎖定表。
請注意當匯出多個數據庫時,--lock-tables分別為每個資料庫鎖定表。因此,該選項不能保證匯出檔案中的表在資料庫之間的邏輯一致性。不同資料庫表的匯出狀態可以完全不同。
mysqldump  -uroot -p --host=localhost --all-databases --lock-tables
--log-error
附加警告和錯誤資訊到給定檔案
mysqldump  -uroot -p --host=localhost --all-databases  --log-error=/tmp/mysqldump_error_log.err
--max_allowed_packet
伺服器傳送和接受的最大包長度。
mysqldump  -uroot -p --host=localhost --all-databases --max_allowed_packet=10240
--net_buffer_length
TCP/IP和socket連線的快取大小。
mysqldump  -uroot -p --host=localhost --all-databases --net_buffer_length=1024
--no-autocommit
使用autocommit/commit 語句包裹表。
mysqldump  -uroot -p --host=localhost --all-databases --no-autocommit
--no-create-db,  -n
只匯出資料,而不新增CREATE DATABASE 語句。
mysqldump  -uroot -p --host=localhost --all-databases --no-create-db
--no-create-info,  -t
只匯出資料,而不新增CREATE TABLE 語句。
mysqldump  -uroot -p --host=localhost --all-databases --no-create-info
--no-data, -d
不匯出任何資料,只匯出資料庫表結構。
mysqldump  -uroot -p --host=localhost --all-databases --no-data
--no-set-names,  -N
等同於--skip-set-charset
mysqldump  -uroot -p --host=localhost --all-databases --no-set-names
--opt
等同於--add-drop-table,  --add-locks, --create-options, --quick, --extended-insert, --lock-tables,  --set-charset, --disable-keys 該選項預設開啟,  可以用--skip-opt禁用.
mysqldump  -uroot -p --host=localhost --all-databases --opt
--order-by-primary
如果存在主鍵,或者第一個唯一鍵,對每個表的記錄進行排序。在匯出MyISAM表到InnoDB表時有效,但會使得匯出工作花費很長時間。 
mysqldump  -uroot -p --host=localhost --all-databases --order-by-primary
--password, -p
連線資料庫密碼
--pipe(windows系統可用)
使用命名管道連線mysql
mysqldump  -uroot -p --host=localhost --all-databases --pipe
--port, -P
連線資料庫埠號
--protocol
使用的連線協議,包括:tcp, socket, pipe, memory.
mysqldump  -uroot -p --host=localhost --all-databases --protocol=tcp
--quick, -q
不緩衝查詢,直接匯出到標準輸出。預設為開啟狀態,使用--skip-quick取消該選項。
mysqldump  -uroot -p --host=localhost --all-databases 
mysqldump  -uroot -p --host=localhost --all-databases --skip-quick
--quote-names,-Q
使用(`)引起表和列名。預設為開啟狀態,使用--skip-quote-names取消該選項。
mysqldump  -uroot -p --host=localhost --all-databases
mysqldump  -uroot -p --host=localhost --all-databases --skip-quote-names
--replace
使用REPLACE INTO 取代INSERT INTO.
mysqldump  -uroot -p --host=localhost --all-databases --replace
--result-file,  -r
直接輸出到指定檔案中。該選項應該用在使用回車換行對(\\r\\n)換行的系統上(例如:DOS,Windows)。該選項確保只有一行被使用。
mysqldump  -uroot -p --host=localhost --all-databases --result-file=/tmp/mysqldump_result_file.txt
--routines, -R
匯出儲存過程以及自定義函式。
mysqldump  -uroot -p --host=localhost --all-databases --routines
--set-charset
新增'SET NAMES  default_character_set'到輸出檔案。預設為開啟狀態,使用--skip-set-charset關閉選項。
mysqldump  -uroot -p --host=localhost --all-databases 
mysqldump  -uroot -p --host=localhost --all-databases --skip-set-charset
--single-transaction
該選項在匯出資料之前提交一個BEGIN SQL語句,BEGIN 不會阻塞任何應用程式且能保證匯出時資料庫的一致性狀態。它只適用於多版本儲存引擎,僅InnoDB。本選項和--lock-tables 選項是互斥的,因為LOCK  TABLES 會使任何掛起的事務隱含提交。要想匯出大表的話,應結合使用--quick 選項。
mysqldump  -uroot -p --host=localhost --all-databases --single-transaction
--dump-date
將匯出時間新增到輸出檔案中。預設為開啟狀態,使用--skip-dump-date關閉選項。
mysqldump  -uroot -p --host=localhost --all-databases
mysqldump  -uroot -p --host=localhost --all-databases --skip-dump-date
--skip-opt
禁用–opt選項.
mysqldump  -uroot -p --host=localhost --all-databases --skip-opt
--socket,-S
指定連線mysql的socket檔案位置,預設路徑/tmp/mysql.sock
mysqldump  -uroot -p --host=localhost --all-databases --socket=/tmp/mysqld.sock
--tab,-T
為每個表在給定路徑建立tab分割的文字檔案。注意:僅僅用於mysqldump和mysqld伺服器執行在相同機器上。注意使用--tab不能指定--databases引數
mysqldump  -uroot -p --host=localhost test test --tab="/home/mysql"
--tables
覆蓋--databases (-B)引數,指定需要匯出的表名,在後面的版本會使用table取代tables。
mysqldump  -uroot -p --host=localhost --databases test --tables test
--triggers
匯出觸發器。該選項預設啟用,用--skip-triggers禁用它。
mysqldump  -uroot -p --host=localhost --all-databases --triggers
--tz-utc
在匯出頂部設定時區TIME_ZONE='+00:00' ,以保證在不同時區匯出的TIMESTAMP 資料或者資料被移動其他時區時的正確性。
mysqldump  -uroot -p --host=localhost --all-databases --tz-utc
--user, -u
指定連線的使用者名稱。
--verbose, --v
輸出多種平臺資訊。
--version, -V
輸出mysqldump版本資訊並退出
--where, -w
只轉儲給定的WHERE條件選擇的記錄。請注意如果條件包含命令解釋符專用空格或字元,一定要將條件引用起來。
mysqldump  -uroot -p --host=localhost --all-databases --where=” user=’root’”
--xml, -X
匯出XML格式.
mysqldump  -uroot -p --host=localhost --all-databases --xml
--plugin_dir
客戶端外掛的目錄,用於相容不同的外掛版本。
mysqldump  -uroot -p --host=localhost --all-databases --plugin_dir=”/usr/local/lib/plugin”
--default_auth
客戶端外掛預設使用許可權。
mysqldump  -uroot -p --host=localhost --all-databases --default-auth=”/usr/local/lib/plugin/<PLUGIN>”
  • unknown option '--no-beep'
解決辦法是:

1. 刪除my.ini [client]下的 no-beep 引數;
2. 在 mysqldump 後加--no-defaults引數,即:mysqldump --no-defualts -h主機IP -u使用者名稱 -p密碼 資料庫 > xxx.sql 。
  • 2 恢復邏輯備份 
#在mysql命令下,用source命令匯入備份檔案:
mysql>  USE 資料庫名;
mysql>  source 備份檔案.sql;
 
注意:只能在cmd介面下執行source命令,不能在mysql工具裡面執行source命令,會報錯,因為cmd是直接呼叫mysql.exe來執行命令的。  
  • 轉自:http://www.cnblogs.com/wangfengming/articles/7883974.html