1.the die is cast?? 一切已成定局
每次我想要演示實際代碼時,我會對mysql客戶端的屏幕就出現的代碼進行調整,將字體改成Courier,使他們看起來與普通文本不一樣(讓大家區別程序代碼和正文)。在這里舉個例子:
mysql> DROP FUNCTION f;
Query OK, 0 rows affected (0.00 sec)
如果實例比較大,則需要在某些行和段落間加注釋,同時我會用將"<--"符號放在頁面的右邊以表示強調。例如:
mysql> CREATE PROCEDURE p ()
-> BEGIN
-> /* This procedure does nothing */ <--
-> END;//
Query OK, 0 rows affected (0.00 sec)
有時候我會將例子中的"mysql>"和"->"這些系統顯示去掉,你可以直接將代碼復制到mysql客戶端程序中(如果你現在所讀的不是電子版的,可以在mysql.com網站下載相關腳本)
所以的例子都已經在Suse 9.2 Linux、Mysql 5.0.3公共版上測試通過。在您閱讀本書的時候,Mysql已經有更高的版本,同時能支持更多OS了,包括Windows,Sparc,HP-UX。因此這里的例子將能正常的運行在您的電腦上。但如果運行仍然出現故障,可以咨詢你認識的資深Mysql用戶,這樣就能得到比較好的支持和幫助。
Why Triggers 為什么要用觸發器
我們在MySQL 5.0中包含對觸發器的支持是由于以下原因:
MySQL早期版本的用戶長期有需要觸發器的要求。
我們曾經許諾支持所有ANSI標準的特性。
您可以使用它來檢查或預防壞的數據進入數據庫。
您可以改變或者取消INSERT, UPDATE以及DELETE語句。
您可以在一個會話中監視數據改變的動作。
在這里我假定大家都讀過"MySQL新特性"叢書的第一集--"MySQL存儲過程",那么大家都應該知道MySQL至此存儲過程和函數,那是很重要的知識,因為在觸發器中你可以使用在函數中使用的語句。特別舉個例子:
復合語句(BEGIN / END)是合法的.
流控制(Flow-of-control)語句(IF, CASE, WHILE, LOOP, WHILE, REPEAT, LEAVE,ITERATE)也是合法的.
變量聲明(DECLARE)以及指派(SET)是合法的.
允許條件聲明.
異常處理聲明也是允許的.
但是在這里要記住函數有受限條件:不能在函數中訪問表.因此在函數中使用以下語句是非法的。
ALTER 'CACHE INDEX' CALL COMMIT CREATE DELETE
DROP 'FLUSH PRIVILEGES' GRANT INSERT KILL
LOCK OPTIMIZE REPAIR REPLACE REVOKE
ROLLBACK SAVEPOINT 'SELECT FROM table'
'SET system variable' 'SET TRANSACTION'
SHOW 'START TRANSACTION' TRUNCATE UPDATE
在觸發器中也有完全一樣的限制.
觸發器相對而言比較新,因此會有(bugs)缺陷.所以我在這里給大家警告,就像我在存儲過程書中所說那樣.不要在含有重要數據的數據庫中使用這個觸發器,如果需要的話在一些以測試為目的的數據庫上使用,同時在你對表創建觸發器時確認這些數據庫是默認的。
Syntax 語法
1. Syntax: Name 語法:命名規則
CREATE TRIGGER <觸發器名稱> <--
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表名稱>
FOR EACH ROW
<觸發器SQL語句>
觸發器必須有名字,最多64個字符,可能后面會附有分隔符.它和MySQL中其他對象的命名方式基本相象.
這里我有個習慣:就是用表的名字+'_'+觸發器類型的縮寫.因此如果是表t26,觸發器是在事件UPDATE(參考下面的點(2)和(3))之前(BEFORE)的,那么它的名字就是t26_bu。
2. Syntax: Time 語法:觸發時間
CREATE TRIGGER <觸發器名稱>
{ BEFORE | AFTER } <--
{ INSERT | UPDATE | DELETE }
ON <表名稱>
FOR EACH ROW
<觸發的SQL語句>
觸發器有執行的時間設置:可以設置為事件發生前或后。
3. Syntax: Event語法:事件
CREATE TRIGGER <觸發器名稱>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE } <--
ON <表名稱>
FOR EACH ROW
<觸發的SQL語句>
同樣也能設定觸發的事件:它們可以在執行insert、update或delete的過程中觸發。
4. Syntax: Table 語法:表
CREATE TRIGGER <觸發器名稱>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表名稱> <--
FOR EACH ROW
<觸發的SQL語句>
觸發器是屬于某一個表的:當在這個表上執行插入、更新或刪除操作的時候就導致觸發器的激活.
我們不能給同一張表的同一個事件安排兩個觸發器。
5. Syntax: Granularity 語法:( :( 步長)觸發間隔
CREATE TRIGGER <觸發器名稱>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表名稱>
FOR EACH ROW <--
<觸發的SQL語句>
觸發器的執行間隔:FOR EACH ROW子句通知觸發器每隔一行執行一次動作,而不是對整個表執行一次。
6. Syntax: Statement 語法:語句
CREATE TRIGGER <觸發器名稱>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表名稱>
FOR EACH ROW
<觸發的SQL語句> <--
觸發器包含所要觸發的SQL語句:這里的語句可以是任何合法的語句,包括復合語句,但是這里的語句受的限制和函數的一樣。
Privileges權限
你必須擁有相當大的權限才能創建觸發器(CREATE TRIGGER)。如果你已經是Root用戶,那么就足夠了。這跟SQL的標準有所不同,我也希望能盡快改成標準的。
因此在下一個版本的MySQL中,你完全有可能看到有一種叫做CREATE TRIGGER的新權限。然后通過這樣的方法賦予:
GRANT CREATE TRIGGER ON <表名稱> TO <用戶或用戶列表>;
也可以通過這樣收回權限:
REVOKE CREATE TRIGGER ON <表名稱> FROM <用戶或用戶列表>;
Referring to OLD and NEW columns 關于舊的和新創建的列的標識
在觸發器的SQL語句中,你可以關聯表中的任意列。但你不能僅使用列的名稱去標識,那會使系統混淆,因為那里可能會有列的新名(這可能正是你要修改的,你的動作可能正是要修改列名),還有列的舊名存在。因此你必須用這樣的語法來標識:
"NEW . column_name"或者"OLD . column_name".這樣在技術上處理(NEW | OLD . column_name)新和舊的列名屬于創建了過渡變量("transition variables")。
對于INSERT語句,只有NEW是合法的;對于DELETE語句,只有OLD才合法;而UPDATE語句可以在和NEW以及OLD同時使用。下面是一個UPDATE中同時使用NEW和OLD的例子。
CREATE TRIGGER t21_au
BEFORE UPDATE ON t22
FOR EACH ROW
BEGIN
SET @old = OLD . s1;
SET @new = NEW.s1;
END;//
現在如果t21表中的s1列的值是55,那么執行了"UPDATE t21 SET s1 = s1 + 1"之后@old的值會變成55,而@new的值將會變成56。
Example of CREATE and INSERT CREATE和INSERT的例子
CREATE table with trigger創建有觸發器的表
這里所有的例程中我都假定大家的分隔符已經設置成//(DELIMITER //)。
CREATE TABLE t22 (s1 INTEGER)//
CREATE TRIGGER t22_bi
BEFORE INSERT ON t22
FOR EACH ROW
BEGIN
SET @x = 'Trigger was activated!';
SET NEW.s1 = 55;
END;//
在最開始我創建了一個名字為t22的表,然后在表t22上創建了一個觸發器t22_bi,當我們要向表中的行插入時,觸發器就會被激活,執行將s1列的值改為55的動作。
INSERT on table w ith a trigger使用觸發器執行插入動作
mysql> INSERT INTO t22 VALUES (1)//
讓我們看如果向表t2中插入一行數據觸發器對應的表會怎么樣?
這里的插入的動作是很常見的,我們不需要觸發器的權限來執行它。甚至不需要知道是否有觸發器關聯。
mysql> SELECT @x, t22.* FROM t22//
+------------------------+------+
| @x | s1 |
+------------------------+------+
| Trigger was activated! | 55 |
+------------------------+------+
1 row in set (0.00 sec)
大家可以看到INSERT動作之后的結果,和我們預期的一樣,x標記被改動了,同時這里插入的數據不是我們開始輸入的插入數據,而是觸發器自己的數據。
Example of a "check" constraint
"check"完整性約束例子
What's a "check" constraint 什么是"check"約束
在標準的SQL語言中,我們可以在(CREATE TABLE)創建表的過程中使用"CHECK (condition)",
例如:
CREATE TABLE t25
(s1 INT, s2 CHAR(5), PRIMARY KEY (s1),
CHECK (LEFT(s2,1)='A'))
ENGINE=INNODB;
這里CHECK的意思是"當s2列的最左邊的字符不是'A'時,insert和update語句都會非法",MySQL的視圖不支持CHECK,我個人是很希望它能支持的。但如果你很需要在表中使用這樣的功能,我建議大家使用觸發器來實現。
CREATE TABLE t25
(s1 INT, s2 CHAR(5),
PRIMARY KEY (s1))
ENGINE=INNODB//
CREATE TRIGGER t25_bi
BEFORE INSERT ON t25
FOR EACH ROW
IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;//
CREATE TRIGGER t25_bu
BEFORE UPDATE ON t25
FOR EACH ROW
IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;//
我只需要使用BEFORE INSERT和BEFORE UPDATE語句就行了,刪除了觸發器不會對表有影響,同時AFTER的觸發器也不能修改NEW的過程變量(transition variables)。為了激活觸發器,我執行了向表中的行插入s1=0的數據,之后只要執行符合LEFT(s2,1) <> 'A'條件的動作都會失敗:
INSERT INTO t25 VALUES (0,'a') /* priming the pump */ //
INSERT INTO t25 VALUES (5,'b') /* gets error '23000' */ //
Don't Believe The Old MySQL Manual
該拋棄舊的MySQL的手冊了
我在這里警告大家不要相信過去的MySQL手冊中所說的了。我們已經去掉了關于觸發器的錯誤的語句,但是仍舊有很多舊版本的手冊在網上,舉個例子,這是一個德國的Url上的:
http://dev.mysql.com/doc/mysql/de/ANSI_diff_Triggers.html.
這個手冊上說觸發器就是存儲過程,忘掉吧,你也已經看見了,觸發器就是觸發器,而存儲過程還是存儲過程。
手冊上還說觸發器可以從其他表上來刪除,或者是當你刪除一個事務的時候激發,無論他說的是什么意思,忘掉吧,MySQL不會去實現這些的。
最后關于說使用觸發器會對查詢速度產生影響的說法也是錯的,觸發器不會對查詢產生任何影響。
Bugs
(不好的東西就不翻譯了)
On December 14 2004, I did an "Advanced Search" in http://bugs.mysql.com for 'trigger' or
'triggers', I found that there were 17 active bugs as of that date. Of course they might disappear
before you read this, but just in case they haven't, I'll mention the important ones. If they're still
there, you'll have to work around them when you're trying triggers.
Bug#5859 DROP TABLE does not drop triggers.
(刪除表的時候沒有自動刪除觸發器)
When you drop a table, dropping the table's triggers should be automatic.
Bug#5892 Triggers have the wrong namespace.
(觸發器的命名空間有錯,你必須在前面加上表的名字才能刪除觸發器,下面是例子)
You have to say "DROP TRIGGER <table name> . <trigger name>".
The correct way is "DROP TRIGGER <trigger name>".
Bug#5894 Triggers with altered tables cause corrupt databases.
(觸發器對表的改變可能會造成數據庫數據被破壞)
Do not alter a table that has a trigger on it, until you know this is fixed.
在數據庫表丟失或損壞的情況下,備份你的數據庫是很重要的。如果發生系統崩潰,你肯定想能夠將你的表盡可能丟失最少的數據恢復到崩潰發生時的狀態。有時,正是 MySQL 管理員造成破壞。管理員已經知道表已破壞,用諸如 vi 或 Emacs 等編輯器試圖直接編輯它們,這對表絕對不是件好事!
備份數據庫兩個主要方法是用 mysqldump 程序或直接拷貝數據庫文件(如用 cp、cpio 或 tar 等)。每種方法都有其優缺點:
mysqldump 與 MySQL 服務器協同操作。直接拷貝方法在服務器外部進行,并且你必須采取措施保證沒有客戶正在修改你將拷貝的表。如果你想用文件系統備份來備份數據庫,也會發生同樣的問題:如果數據庫表在文件系統備份過程中被修改,進入備份的表文件主語不一致的狀態,而對以后的恢復表將失去意義。文件系統備份與直接拷貝文件的區別是對后者你完全控制了備份過程,這樣你能采取措施確保服務器讓表不受干擾。
mysqldump 比直接拷貝要慢些。
mysqldump 生成能夠移植到其它機器的文本文件,甚至那些有不同硬件結構的機器上。直接拷貝文件不能移植到其它機器上,除非你正在拷貝的表使用 MyISAM 存儲格式。ISAM 表只能在相似的硬件結構的機器上拷貝。在 MySQL 3.23 中引入的 MyISAM 表存儲格式解決了該問題,因為該格式是機器無關的,所以直接拷貝文件可以移植到具有不同硬件結構的機器上。只要滿足兩個條件:另一臺機器必須也運行 MySQL 3.23 或以后版本,而且文件必須以 MyISAM 格式表示,而不是 ISAM 格式。
不管你使用哪種備份方法,如果你需要恢復數據庫,有幾個原則應該遵守,以確保最好的結果:
定期實施備份。建立一個計劃并嚴格遵守。
讓服務器執行更新日志。當你在崩潰后需要恢復數據時,更新日志將幫助你。在你用備份文件恢復數據到備份時的狀態后,你可以通過運行更新日志中的查詢再次運用備份后面的修改,這將數據庫中的表恢復到崩潰發生時的狀態。
以文件系統備份的術語講,數據庫備份文件代表完全傾倒(full dump),而更新日志代表漸進傾倒(incremental dump)。
使用一種統一的和易理解的備份文件命名機制。象 backup1、buckup2 等不是特別有意義。當實施你的恢復時,你將浪費時間找出文件里是什么東西。你可能發覺用數據庫名和日期構成備份文件名會很有用。例如:
%mysqldump samp_db >/usr/archives/mysql/samp_db.1999-10-02
%mysqldump menagerie >/usr/archives/mysql/menagerie.1999-10-02
你可能想在生成備份后壓縮它們。備份一般都很大!你也需要讓你的備份文件有過期期限以避免它們填滿你的磁盤,就象你讓你的日志文件過期那樣。
用文件系統備份備份你的備份文件。如果遇上了一個徹底崩潰,不僅清除了你的數據目錄,也清除了包含你的數據庫備份的磁盤驅動器,你將真正遇上了麻煩。
也要備份你的更新日志。
將你的備份文件放在不同于用于你的數據庫的文件系統上。這將降低由于生成備份而填滿包含數據目錄的文件系統的可能性。
用于創建備份的技術同樣對拷貝數據庫到另一臺機器有用。最常見地,一個數據庫被轉移到了運行在另一臺主機上的服務器,但是你也可以將數據轉移到同一臺主機上的另一個服務器。
1 使用 mysqldump 備份和拷貝數據庫
當你使用 mysqldumo 程序產生數據庫備份文件時,缺省地,文件內容包含創建正在傾倒的表的 CREATE 語句和包含表中行數據的 INSERT 語句。換句話說,mysqldump 產生的輸出可在以后用作 mysql 的輸入來重建數據庫。
你可以將整個數據庫傾倒進一個單獨的文本文件中,如下:
%mysqldump samp_db >/usr/archives/mysql/samp_db.1999-10-02
輸出文件的開頭看起來象這樣:
# MySQL Dump 6.0# # Host: localhost Database: samp_db#-------------
--------------------------# Server version 3.23.2-alpha-log## Table st
ructure for table absence#CREATE TABLE absence( student_id int(10)
unsigned DEFAULT 0 NOT NULL, date date DEFAULT 0000-00-00 NOT NUL
L, PRIMARY KEY (student_id,date));## Dumping data for table absence
#INSERT INTO absence valueS (3,1999-09-03);INSERT INTO absence value
S (5,1999-09-03);INSERT INTO absence valueS (10,1999-09-08);......
文件剩下的部分有更多的INSERT和CREATE TABLE語句組成。如果你想壓縮備份,使用類似如下的命令:
%mysqldump samp_db | gzip >/usr/archives/mysql/samp_db.1999-10-02.gz
如果你要一個龐大的數據庫,輸出文件也將很龐大,可能難于管理。如果你愿意,你可以在 mysqldump 命令行的數據庫名后列出單獨的表名來傾到它們的內容,這將傾倒文件分成較小、更易于管理的文件。下例顯示如何將 samp_db 數據庫的一些表傾到進分開的文件中:
%mysqldump samp_db student score event absence >grapbook.sql
%mysqldump samp_db member president >hist-league.sql
如果你生成準備用于定期刷新另一個數據庫內容的備份文件,你可能想用 --add- drop-table 選項。這告訴服務器將 DROP TABLE IF EXISTS 語句寫入備份文件,然后,當你取出備份文件并把它裝載進第二個數據庫時,如果表已經存在,你不會得到一個錯誤。
如果你倒出一個數據庫以便能把數據庫轉移到另一個服務器,你甚至不必創建備份文件。要保證數據庫存在于另一臺主機,然后用管道傾倒數據庫,這樣 mysql 能直接讀取 mysqldump 的輸出。例如:你想從主機 pit- viper.snake.net 拷貝數據庫 samp_db 到 boa.snake.net,可以這樣很容易做到:
%mysqladmin -h boa.snake.net create samp_db
%mysqldump samp_db | mysql -h boa.snake.net samp_db
以后,如果你想再次刷新 boa.snake.net 上的數據庫,跳過 mysqladmin 命令,但要對 mysqldump 加上--add-drop-table 以避免的得到表已存在的錯誤:
%mysqldump --add-drop-table samp_db | mysql -h boa.snake.net samp_db
mysqldump 其它有用的選項包括:
--flush-logs 和 --lock-tables 組合將對你的數據庫檢查點有幫助。--lock-tables 鎖定你正在傾倒的所有表,而 --flush-logs 關閉并重新打開更新日志文件,新的更新日志將只包括從備份點起的修改數據庫的查詢。這將設置你的更新日志檢查點位備份時間。(然而如果你有需要執行個更新的客戶,鎖定所有表對備份期間的客戶訪問不是件好事。)
如果你使用 --flush-logs 設置檢查點到備份時,有可能最好是傾倒整個數據庫。
如果你傾倒單獨的文件,較難將更新日志檢查點與備份文件同步。在恢復期間,你通常按數據庫為基礎提取更新日志內容,對單個表沒有提取更新的選擇,所以你必須自己提取它們。
缺省地,mysqldump 在寫入前將一個表的整個內容讀進內存。這通常確實不必要,并且實際上如果你有一個大表,幾乎是失敗的。你可用 --quick 選項告訴 mysqldump 只要它檢索出一行就寫出每一行。為了進一步優化傾倒過程,使用 --opt 而不是 --quick。--opt 選項打開其它選項,加速數據的傾倒和把它們讀回。
用 --opt 實施備份可能是最常用的方法,因為備份速度上的優勢。然而,要警告你,--opt 選項確實有代價,--opt 優化的是你的備份過程,不是其他客戶對數據庫的訪問。--opt 選項通過一次鎖定所有表阻止任何人更新你正在傾倒的任何表。你可在一般數據庫訪問上很容易看到其效果。當你的數據庫一般非常頻繁地使用,只是一天一次地調節備份。
一個具有 --opt 的相反效果的選項是 --dedayed。該選項使得 mysqldump 寫出 INSERT DELAYED 語句而不是 INSERT 語句。如果你將數據文件裝入另一個數據庫并且你想是這個操作對可能出現在該數據庫中的查詢的影響最小,--delayed 對此很有幫助。
--compress 選項在你拷貝數據庫到另一臺機器上時很有幫助,因為它減少網絡傳輸字節的數量。下面有一個例子,注意到 --compress 對與遠端主機上的服務器通信的程序才給出,而不是對與本地主機連接的程序:
%mysqldump --opt samp_db | mysql --compress -h boa.snake.net samp_db
2 使用直接拷貝數據庫的備份和拷貝方法
另一種不涉及 mysqldump 備份數據庫和表的方式是直接拷貝數據庫表文件。典型地,這用諸如 cp、tar 或 cpio 實用程序。本文的例子使用 cp。
當你使用一種直接備份方法時,你必須保證表不在被使用。如果服務器在你則正在拷貝一個表時改變它,拷貝就失去意義。
保證你的拷貝完整性的最好方法是關閉服務器,拷貝文件,然后重啟服務器。如果你不想關閉服務器,要在執行表檢查的同時鎖定服務器。如果服務器在運行,相同的制約也適用于拷貝文件,而且你應該使用相同的鎖定協議讓服務器“安靜下來”。
假設服務器關閉或你已經鎖定了你想拷貝的表,下列顯示如何將整個 samp_db 數據庫備份到一個備份目錄(DATADIR 表示服務器的數據目錄):
%cd DATADIR%cp -r samp_db /usr/archive/mysql
單個表可以如下備份:
%cd DATADIR/samp_db%cp member.* /usr/archive/mysql/samp_db%cp score.*
/usr/archive/mysql/samp_db ....
當你完成了備份時,你可以重啟服務器(如果關閉了它)或釋放加在表上的鎖定(如果你讓服務器運行)。
要用直接拷貝文件把一個數據庫從一臺機器拷貝到另一臺機器上,只是將文件拷貝到另一臺服務器主機的適當數據目錄下即可。要確保文件是 MyIASM 格式或兩臺機器有相同的硬件結構,否則你的數據庫在另一臺主機上有奇怪的內容。你也應該保證在另一臺機器上的服務器在你正在安裝數據庫表時不訪問它們。
3 復制數據庫(Replicating Database)
復制(Replication)類似于拷貝數據庫到另一臺服務器上,但它的確切含義是實時地保證兩個數據庫的完全同步。這個功能將在 3.23 版中出現,而且還不很成熟,因此本文不作詳細介紹。
4 用備份恢復數據
數據庫損壞的發生有很多原因,程度也不同。如果你走運,你可能僅損壞一兩個表(如掉電),如果你倒霉,你可能必須替換整個數據目錄(如磁盤損壞)。在某些情況下也需要恢復,比如用戶錯誤地刪除了數據庫或表。不管這些倒霉事件的原因,你將需要實施某種恢復。
如果表損壞但沒丟失,嘗試用 myisamchk 或 isamchk 修復它們,如果這樣的損壞可有修復程序修復,你可能根本不需要使用備份文件。
恢復過程涉及兩種信息源:你的備份文件和個更新日志。備份文件將表恢復到實施備份時的狀態,然而一般表在備份與發生問題之間的時間內已經被修改,更新日志包含了用于進行這些修改的查詢。你可以使用日志文件作為 mysql 的輸入來重復查詢。這已正是為什么要啟用更新日志的原因。
恢復過程視你必須恢復的信息多少而不同。實際上,恢復整個數據庫比單個表跟容易,因為對于數據庫運用更新日志比單個表容易。
4.1 恢復整個數據庫
首先,如果你想恢復的數據庫是包含授權表的 mysql 數據庫,你需要用 --skip -grant-table 選項運行服務器。否則,它會抱怨不能找到授權表。在你已經恢復表后,執行 mysqladmin flush-privileges 告訴服務器裝載授權標并使用它們。
將數據庫目錄內容拷貝到其它某個地方,如果你在以后需要它們。
用最新的備份文件重裝數據庫。如果你用 mysqldump 產生的文件,將它作為 mysql 的輸入。如果你用直接從數據庫拷貝來的文件,將它們直接拷回數據庫目錄,然而,此時你需要在拷貝文件之前關閉數據庫,然后重啟它。
使用更新日志重復做備份以后的修改數據庫表的查詢。對于任何可適用的更新日志,將它們作為 mysql 的輸入。指定 --one-database 選項使得 mysql 只執行你有興趣恢復的數據庫的查詢。如果你知道你需要運用所有更新日志文件,你可以在包含日志的目錄下使用這條命令:
% ls -t -r -1 update.[0-9]* | xargs cat | mysql --one-database db_name
ls 命令生成更新日志文件的一個單列列表,根據服務器產生它們的次序排序(主意:如果你修改任何一個文件,你將改變排序次序,這導致更新日志一錯誤的次序被運用。)
很可能你會是運用某幾個更新日志。例如,自從你備份以來產生的更新日志被命名為 update.392、update.393 等等,你可以這樣重新運行:
%mysql --one-database db_name < update.392
%mysql --one-database db_name < update.393
.....
如果你正在實施恢復且使用更新日志恢復由于一個錯誤建議的 DROP DATABASE、DROP TABLE 或 DELETE 語句造成丟失的信息,在運用更新日志之前,要保證從其中刪除這些語句。
4.2 恢復單個表
恢復單個表較為復雜。如果你用一個由 mysqldump 生成的備份文件,并且它不包含你感興趣的表的數據,你需要從相關行中提取它們并將它們用作 mysql 的輸入。這是容易的部分。難的部分是從只運用于該表的更新日志中拉出片斷。你會發覺 mysql_find_rows 實用程序對此很有幫助,它從更新日志中提取多行查詢。
另一個可能性是使用另一臺服務器恢復整個數據庫,然后拷貝你想要的表文件到原數據庫中。這可能真的很容易!當你將文件拷回數據庫目錄時,要確保原數據庫的服務器關閉。
在Web應用中,經常需要動態生成圖片,比如實時股市行情,各種統計圖等等,這種情況下,圖片只能在服務器內存中動態生成并發送給用戶,然后在瀏覽器中顯示出來。http://www.javaworld.com.tw/confluence/pages/viewpage.action?pageId=833
第一種方法:在tomcat中的conf目錄中,在server.xml中的,<host/>節點中添加:
<Context path="/hello" docBase="D:eclipse3.2.2forwebtoolsworkspacehelloWebRoot" debug="0" privileged="true">
</Context>
至于Context 節點屬性,可詳細見相關文檔。
第二種方法:將web項目文件件拷貝到webapps 目錄中。
第三種方法:很靈活,在conf目錄中,新建 Catalina(注意大小寫)\localhost目錄,在該目錄中新建一個xml文件,名字可以隨意取,只要和當前文件中的文件名不重復就行了,該xml文件的內容為:
<Context path="/hello" docBase="D:eclipse3.2.2forwebtoolsworkspacehelloWebRoot" debug="0" privileged="true">
</Context>
1、前言:
CVS是版本控制的利器,目前在Linux和Windows下都有不同版本;但是國內大多數應用介紹都是基于Linux等開放源代碼的開放性軟件組織,而且講解的也不系統,讓人摸不著頭腦;Windows下的CVS使用介紹更是了了無幾。
本文是針對Windows的LAN環境下使用CVS的經驗介紹,一步一步的向您介紹如何配置和使用CVS的服務器端和客戶端。同時,本文只使用到了CVS當中最基本的東西,還有很多更為高級的東西,本文暫不涉及。下面是本文的另一個連接映射,歡迎大家討論使用,共同進步。
文章連接http://www.kuihua.net/book/list.asp?id=66
論壇連接http://www.kuihua.net/bbs/dispbbs.asp?boardID=1&;RootID=670&ID=670
2、安裝版本:
2.1、服務器端(CVSNT)
1. 本文使用的是CVSNT-2.0.4,這是一個比較穩定的版本,不要使用最新的CVSNT-2.1.1,本人在使用中發現有比較嚴重的Bug。
2. 下載連接http://www.cvsnt.org 目前,它提供2.0.6和2.1.1版本的下載。
3. 上面連接還提供源代碼,有興趣的朋友還可以下載下來仔細研究:)。
4. 有心的朋友,仔細觀察就會發現http://www.cvsnt.org 并沒有提供任何客戶端的下載,那是因為CVS.exe既可以用于服務器端又可以用于客戶端,WinCVS是為了客戶端使用的方便而定制的外殼。(關于這一點,本人未得到任何證實,只是本人在使用過程中的一種體會,歡迎大家討論。)
2.2、客戶端(WinCVS)
1. 本文使用的是WinCVS-1.3b13,這應該是一個最新版本:),本人在使用過程中并沒有發現有任何嚴重的Bug。
2. 下載連接http://sourceforge.net/projects/cvsgui/
3. 此網站還提供豐富的CVS文檔和相關源代碼,以及多個OS下面的相關文檔和代碼;有收藏癖的朋友有福了:)。
4. WinCVS-1.3b13 使用的CVSNT的版本是CVSNT-2.0.2,在與服務器端的CVSNT-2.0.4 版本配合使用時,未發現任何不兼容或沖突現象。
5. 在本人的系統中用cvs version命令顯示的結果如下:
Client: Concurrent Versions System (CVSNT) 2.0.2 (client/server)
Server: Concurrent Versions System (CVSNT) 2.0.4 (client/server)
3、服務器端(CVSNT)的安裝與配置:
3.1、服務器端機器和環境配置:
1. 操作系統:Windows 2000 Professional SP2中文版
2. 機器名稱:Server
3. 機器地址:192.168.0.6 (內部IP)
4. 網絡環境:100兆交換局域網
5. 硬盤分區格式:FAT32與NTFS都可以。
6. 準備2個CVSNT的工作目錄:
F:\KHRoot (存放自己源代碼的根目錄)
F:\KHTemp (存放CVS出錯信息的目錄)
7. 本機上存在有的用戶列表:(由NT或本機的使用者創建)
Administrator (系統管理員)
Jackey (普通用戶)
Goury (普通用戶)
Riolee (普通用戶)
3.2、安裝CVSNT:
1. 下載CVSNT-2.0.4;使用administrator登陸到Server機器上。
2. 雙擊自解壓的exe文件,選擇Full Install,其它按照默認方式安裝;安裝完畢后可以在服務控制器中發現多了2個服務:cvsnt與cvslocking
3. 發送Service Control Panel到桌面,形成快捷方式。
4. 安裝程序會自動將CVS安裝路徑,設置到系統的Path環境變量當中,因此使用者可以在控制臺(cmd)中任意位置執行cvs.exe,這一點對下面的配置很重要!!
3.3、配置CVSNT服務器:
1. 雙擊Service Control Panel快捷方式,在Service Status頁面,確認2個服務正常和穩定運行。
2. 選擇Repository頁面,點按Add按鈕,選擇已經準備好的F:\KHRoot這個目錄,確認,OK,Yes,這時會在F:\KHRoot下面建立CVSRoot目錄,這是CVS默認的管理目錄(默認模塊)。如果報錯,那是系統Path路徑未設置正確。
3. 選擇Advanced頁面,勾上Use local users for pserver ...,(Why? I don't know!J),在Temporary欄選擇已經準備好的F:\KHTemp,確認,OK。
4. 點按【應用】按鈕,確認,退出,OK,搞定!!
3.4、小結:
1. 至此,CVSNT服務器端基本配置完畢,下面進行WinCVS的使用和管理。
2. 由于CVS支持遠程管理,也就是客戶端與服務器集成的特性,因此,我們將添加用戶、權限控制、模塊維護等所有的管理工作都放到遠端(WinCVS)進行管理,服務器端這時可以Ctrl+Atl+Del進入鎖定狀態了,下面的所有工作都交給遠端的WinCVS來進行管理。
4 客戶端(WinCVS)的安裝與配置:
4.1 客戶端機器和環境配置:
1. 操作系統:Windows 2000 Professional SP2中文版
2. 機器名稱:YCW2000
3. 機器地址:192.168.0.2 (內部IP)
4. 網絡環境:100兆交換局域網,可以直接訪問到Server
5. 硬盤分區格式:FAT32與NTFS都可以。
4.2 安裝WinCVS:
1. 下載WinCVS 1.3b13,全部按照默認安裝就可以了。
2. 啟動WinCVS,開始使用。特別注意:以下的所有操作都是在YCW2000(192.168.0.2)這臺機器上遠程完成的,此時的Server(192.168.0.6)主機已經進入了鎖定狀態。
5 管理員使用WinCVS進行遠程管理:
5.1 配置WinCVS成管理員狀態:
1. 準備管理員工作目錄:(在YCW2000機器上)
E:\CVSClient\Admin (管理員工作目錄)
E:\CVSTemp (WinCVS臨時目錄)
2. 第一次啟動WinCVS時會自動彈出Preferences配置頁面,也可以通過Admin=>Preference菜單進入;第一次使用時需要配置如下的3個頁面:
General頁面設置:
注:按照圖示方式輸入即可,需要注意的是Path部分的格式是Unix路徑格式,它指的是CVSNT端設置的工作根目錄。
CVS頁面設置: 注:Home路徑是設置密碼等文件的存放位置,必須指定,否則在登陸時,WinCVS也要彈出設置框。這個Home路徑需要Python.exe這個外掛程序才有效。這里選擇已經準備好的路徑:E\CVSTemp
WinCVS頁面設置:
注:此頁面設置WinCVS的外掛編輯程序,通常使用UltraEdit比較方便。
3. 設置管理員的工作路徑:可以點按圖標 ,或View=>Browse Location=>Change...菜單進行設置,選擇已經準備好的路徑:E:\CVSClient\Admin,確認,OK,這時此目錄將出現在WinCVS的左邊導航欄【Workspace】內。
4. 至此,WinCVS就被配置成了遠程的管理員使用狀態,下面進行一般管理員需要的基本操作演練。演練的內容為:Administrator需要管理Jackey,Goury,Riolee三個用戶,分別為這3個用戶建立工作目錄,每個人只能訪問自己的工作目錄。同時,只有Administrator能夠進行權限分配,其它人沒有任何管理權限。
5.2 管理員進行管理演練:
1. 登陸遠程CVSNT:
◇ 選擇Admin=>Login菜單,默認設置,OK。
◇ 彈出密碼輸入框,確認,OK。注意觀察輸出框【OutPut】的返回結果。
2. Checkout默認模塊:(CVSRoot管理模塊)
◇ 在左邊導航欄【Workspace】內,選擇【Admin】點按右鍵,選擇【Checkout
modules...】,在【Checkout settings】中輸入CVSRoot,確定,OK。如下圖:
◇ 如果成功的話,會在【Admin】欄下增加一個【CVSRoot】目錄。表示您已經將【
CVSRoot】這個管理模塊下載到本地了。
3. CVS中目錄權限介紹:
◇ 系統支持的目錄權限列表:
r (讀取權限)
w (寫入權限)
c (創建和刪除權限)
n (沒有任何權限)
◇ 默認情況下,任何用戶都擁有任何目錄的所有權限。
◇ 任何情況下只有目錄的擁有者和Administrator才有權力更改目錄的使用權限。下面將會介紹如何修改目錄權限和目錄的擁有者。
4. 修改CVSRoot的權限:只讓Administrator擁有rcw三種全部權限。
◇ 選中剛剛下載的【CVSRoot】模塊,【Ctrl+L】或Admin=>Command Line...,彈出Command Line Settings對話框,直接執行CVS命令。
◇ 取消所有用戶的默認權限:cvs chacl default:n 回車,OK,完成。
◇ 設置Administrator擁有所有權限:cvs chacl administrator:rcw 回車,OK,完成。
◇ 更改【CVSRoot】的擁有者:cvs chown administrator 回車,OK,完成。
◇ 查看【CVSRoot】的權限狀態:cvs lsacl 回車,OK,在【Output】中顯示:
Owner: administrator
default:n
administrator:rwc
◇【CVSRoot】的權限配置完畢。
5. 編寫代碼庫中的模塊文件,便于多用戶下載方便。
l 需要自己編寫的模塊文件格式如下:(實現基本功能)
【模塊一的描述】【n個空格或參數】【相對目錄路徑一(DirA)】
【模塊二的描述】【n個空格或參數】【相對目錄路徑二(DirB)】
......
【模塊X的描述】【n個空格或參數】【相對目錄路徑X(DirX)】
◇【描述信息】與【相對路徑】在字面上不一致時,需要使用-a參數。
◇ 【相對路徑】指的是CVS會自動帶上根路徑,這里是F:\KHRoot,所以上面例子的完整路徑為:F:\KHRoot\DirA
◇ 了解了模塊文件結構,現在來實際操作一把:雙擊【CVSRoot】模塊下的modules文件,用UltraEdit打開進行編輯。
◇ 為Jackey,Goury,Riolee三個用戶分配工作目錄和完成其它模塊描述。
CVSRoot CVSRoot
Jackey工作目錄 -a Jackey
Goury工作目錄 -a Goury
Riolee工作目錄 -a Riolee
◇ 編輯完畢,存盤。回到WinCVS,選中modules這個文件【Ctlr+M】或右鍵選擇【Commit selection...】,默認設置,【確認】,OK,完成上傳。
6 . 為三個用戶分別上傳工作目錄:
◇ 在YCW2000機器上的E:\CVSClient\Admin分別建立三個目錄分別名為:Jackey,Goury,Riolee,作為臨時交換目錄。
◇ 在新創建的每個目錄中用UltraEdit或拷貝一個Readme.txt作為引子文件!!:)
◇ 然后,回到WinCVS,在【Workspace】欄的【Admin】目錄下形成如下的目錄結構:
◇ 分別選中Goury,Jackey,Riolee,右鍵,點按【Import Module】,選擇【Continue】,其它全部使用默認值,【確定】,OK,完成上傳工作。
◇ 仔細觀察【Output】窗口,確認都成功上傳了。
◇ 轉移到系統的Explore程序中,刪除E:\CVSClient\Admin目錄下的Jackey,Goury,Riolee三個目錄。然后回到WinCVS當中。(一定要刪除!!!:)
◇ 至此,就完成了工作目錄的上傳工作。
7. 【Checkout】下載3個用戶的工作目錄到【Admin】目錄下:
◇ 在【Workspace】欄選擇【Admin】目錄,右鍵,點按【Checkout Module...】,如下圖:
◇ 選擇【...】,得到CVSNT上最新的模塊配置情況,彈出如下的信息框:
◇ 這個結構圖就是剛才在modules當中編寫的模塊文件格式信息。選擇【Jackey工作目錄】,下載到YCW2000機器的E:\CVSClient\Admin目錄下。
◇ 按照以上操作,依次分別下載【Goury工作目錄】和【Riolee工作目錄】。形成如下狀態:
8. 為三個用戶分別設置各自目錄的訪問權限。(只有自己才能訪問自己的工作目錄)
◇ 選中【Goury】目錄,【Ctrl+L】或Admin=>Command Line...,彈出Command Line Settings對話框,直接執行CVS命令。
◇ 取消所有用戶的默認權限:cvs chacl default:n 回車,OK,完成。
◇ 設置Goury擁有所有權限:cvs chacl goury:rcw 回車,OK,完成。
◇ 查看【CVSRoot】的權限狀態:cvs lsacl 回車,OK,在【Output】中顯示:
Owner: administrator
default:n
goury:rwc
◇ 按照以上的方法依次分別設置【Jackey】與【Riolee】的工作目錄訪問權限。
◇ 至此,完成了3個用戶的目錄權限分配。注意,雖然Administrator也沒有權力再次【Checkout】那3個用戶的工作目錄,但是它是這些目錄的擁有者又是Administrator,因此,只有它才有權力更改這些目錄的訪問權限。
9. CVSNT系統中的用戶管理原則:
◇ CVSNT的用戶與本機(這里是Server機器)上的NT用戶是相關聯的,即CVSNT用的全是本機上存在的已有用戶,因此在默認情況下可以不用設置任何用戶名,只要使用本機上已經存在的用戶名就可以用WinCVS進行登陸。
◇ 只有用Administrator身份登陸到CVSNT系統中,才有權力進行新用戶的創建和刪除。
◇ 使用CVS創建的新用戶,必須與服務器端機器上的NT用戶相綁定,才能生效;因此,這個新用戶實際上是綁定它的NT用戶的一個替身,在CVS系統中稱為"別名"。
◇ 一個NT用戶可以有多個‘替身'或‘別名',充當多個CVS用戶。
10. 用WinCVS進行新用戶的添加和刪除。(確保使用Administrator登陸)
◇ 【Ctrl+L】或Admin=>Command Line...,彈出Command Line Settings對話框,直接執行CVS命令。
◇ 添加新用戶【Killer】:cvs passwd -a Killer 回車,設置密碼,OK,完成。
◇ 綁定【Killer】到【Jackey】:cvs passwd -r Jackey Killer 回車,設置密碼,OK,完成。
◇ 兩次輸入的密碼可以不同,但以第二次輸入的密碼為最終密碼。
◇ 刪除用戶【Killer】:cvs passwd -X Killer 回車,OK,完成。
◇ 其它特殊的功能查看passwd命令的幫助。
11.使用完畢后,一定要【Logout】,因為WinCVS退出時并不會自動注銷自己在遠端的會話;這樣做是為了防止其它人接著打開WinCVS,不用登陸就可以完成你能進行的所有操作了。
6 WinCVS中常見的特殊操作:
6.1 如何刪除下載的文件或目錄:
1. 選中下載的某個或多個文件,執行【Remove】命令。
2. 再次選中這些文件,執行【Commit】命令就完成了刪除文件的操作。
3. 本質上CVS是不會刪除任何文件和目錄的,即使是執行了以上操作,刪除了某些文件,遠端CVS實際執行的是將提交刪除的文件放到了一個叫【Attic】的目錄下,因此,這些被刪除的文件是可以通過一定的方法恢復的。
6.2 如何恢復已經刪除的文件或目錄:
1. 在執行了【Remove】命令之后恢復文件。
◇ 【Ctrl+L】直接輸入命令cvs add xxxxx,或執行【Add Selection】界面操作。
◇ 這樣就可以直接恢復還未提交的刪除文件。
2. 在執行了【Commit】命令之后恢復文件。
◇ 只能用【Ctrl+L】直接輸入命令cvs add xxxxx,這時會得到一個空的文件。
◇ 選中這個空文件,執行【Update】操作,得到這個文件的實體。
◇ 再次選中這個文件,執行【Commit】操作,得到這個文件最新版本。
3. 由于CVS系統中本質上不會刪除任何目錄,因此,談不上對目錄的恢復,但是CVS系統默認情況下是要在用戶本機上(如:YCW2000)要刪除空目錄,因此,可以用如下方法得到已被刪除的空目錄:cvs checkout -p xxx,也可以在Admin=>Preference的【Globals】頁面進行設置。
4. 可見,CVS系統能夠保證:只要上傳到服務器的文件,無論你怎么在遠程進行如何的操作,正常的或非正常的操作,都可以用Administrator登陸上去,通過以上的方法找到丟失的文件。除非用戶進入到遠端服務器,將文件手動刪除,那就沒辦法了:)
6.3 如何得到以前版本的文件:
1. 有時我們需要得到以前版本的文件,而WinCVS默認方式只傳遞最新的版本。
2. 選中某個文件,【Ctrl+G】或右鍵,點按【Graph selection...】,使用默認設置,就可以得到該文件所以版本的圖形結構描述。
3. 選中一個版本,右鍵,點按【Retrieve revision】,就可以得到相應的老版本文件。當然也可以得到最新版本的文件:)
6.4 有時WinCVS會變得異常緩慢,怎么辦?
1. 確認安裝了WinCVS的機器上沒有安裝CVSNT服務器端,因為它們使用的版本有可能不一致。
2. 只安裝了WinCVS,但以前安裝過其它版本的WinCVS,怎么辦?
3. 先卸載所有的WinCVS系統,刪除安裝目錄下的殘留文件。
4. 打開注冊表編輯器,全程查找cvs關鍵字,找到一個刪除一個,一直到找不到為止!!:)
5. 重新安裝WinCVS,這個問題基本上就可以解決了,我就是這樣解決,不曉得你那里如何?:)
7 其它說明:
1. 本文的重點在介紹如何讓使用者搭建CVSNT+WinCVS這個系統,因此重點介紹了管理員的常用操作,至于一般用戶使用到的操作,相對比較簡單和單一,使用WinCVS的次數多了,很快就會熟悉它了。
2. 這篇文檔只是窺探了CVS的一點皮毛而已,CVS當中還有很多高級的用法,以及上百個命令,還有很多新鮮的管理源代碼的方法,比如:tag,branch等模式;因此,熱烈歡迎大家積極探索,不斷共享,不斷進步。。。。。。。。
3. 另外,cvs.html這個幫助,里面的信息也很豐富,但是,很多地方寫得不夠清楚,需要不斷猜測和實踐才能知道怎么回事,本文的很多經驗都是看這個幫助,如此這般,采用這個笨辦法得到的。。。。。。
4. 最后,祝愿看到此文的人,得到的幫助、提高等好處大于或等于浪費的時間、反而退步等壞處!!