FileOutputStream os=Activity.this.openFileOutput(“txtme.txt”,MODE_PRIVATE);—>在/data/data/包名/files/目錄下會(huì)創(chuàng)建txtme.txt文件(如果該文件不存在的話),MODE_PRIVATE的文件是應(yīng)用程序私有的,MODE_WORLD_READABLE則所有應(yīng)用程序都可以訪問(wèn)的,MODE_WORLD_WRITEABLE所有應(yīng)用程序都可以寫,mode_APPEND則是如果要?jiǎng)?chuàng)建的文件存在則新寫入的數(shù)據(jù)不會(huì)覆蓋以前的數(shù)據(jù)。
package wl.android;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.henii.service.FileService;
import android.content.Context;
import android.test.AndroidTestCase;
import android.util.Log;
public class DataSaveTest extends AndroidTestCase {
private static final String TAG = "DataSaveTest";
public void testSave() throws Exception{
//openFileOutput方法的第一個(gè)參數(shù)用于指定文件名稱,不能包含路徑分割符“/”,
//參數(shù)二為對(duì)文件的訪問(wèn)權(quán)限,如果希望有多個(gè)權(quán)限,則寫成如下形式:
//Context.MODE_PRIVATE + Context.MODE_APPEND (注意是用“+”號(hào))
//如果文件不存在,Android會(huì)自動(dòng)創(chuàng)建它。
//創(chuàng)建的文件保存在/data/data/Activity所在的包/files目錄,
//如/data/data/com.henii.android/files/myText.txt,
//--------------------------------------------------------
//通過(guò)Window-Show View-Other,在對(duì)話窗口中展開Android文件夾,
//選擇下面的File Explorer視圖,就可以看到創(chuàng)建的文件了
//-------------------------------------------------------
//this.getContext方法獲取相應(yīng)的當(dāng)前應(yīng)用Activity的上下文環(huán)境
FileOutputStream outStream = this.getContext().openFileOutput("myText.txt", Context.MODE_PRIVATE + Context.MODE_APPEND);
FileService.save(outStream, "Henii");
}
public void testRead()throws Exception{
//如果您要讀取其他應(yīng)用的文件的話,你要完整寫出這個(gè)文件的路徑,如:
//如/data/data/com.henii.android/files/myText.txt,
//而且不能使用openFileInput方法(因?yàn)檫@個(gè)方法的參數(shù)是不能帶分隔符“/”的)
//所以您只能使用最一般的讀取文件的方法進(jìn)行讀取
FileInputStream inStream = this.getContext().openFileInput("myText.txt");
String henii = FileService.read(inStream);
Log.i(TAG, henii);
}
}
摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*以下為圖片處理類*/ <?php/* 圖片處理函數(shù)功能:縮放、剪切、相框、水印、銳化、旋轉(zhuǎn)、翻轉(zhuǎn)、透明度、反色 處理并保存歷史記錄的思路:當(dāng)有圖片有改動(dòng)時(shí)自動(dòng)生成一...
閱讀全文
1 引言
Mysql的觸發(fā)器和存儲(chǔ)過(guò)程一樣,都是嵌入到mysql的一段程序。觸發(fā)器是mysql5新增的功能,目前線上鳳巢系統(tǒng)、北斗系統(tǒng)以及哥倫布系統(tǒng)使用的數(shù)據(jù)庫(kù)均是mysql5.0.45版本,很多程序比如fc-star管理端,sfrd(das),dorado都會(huì)用到觸發(fā)器程序,實(shí)現(xiàn)對(duì)于數(shù)據(jù)庫(kù)增、刪、改引起事件的關(guān)聯(lián)操作。本文介紹了觸發(fā)器的類型和基本使用方法,講述了觸發(fā)器使用中容易產(chǎn)生的誤區(qū),從mysql源碼中得到觸發(fā)器執(zhí)行順序的結(jié)論,本文最后是實(shí)戰(zhàn)遭遇的觸發(fā)器經(jīng)典案例。沒有特殊說(shuō)明時(shí),本文的實(shí)驗(yàn)均基于mysql5.0.45版本。
2 Mysql觸發(fā)器的類型
2.1 Mysql觸發(fā)器的基本使用
創(chuàng)建觸發(fā)器。創(chuàng)建觸發(fā)器語(yǔ)法如下:
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
其中trigger_name標(biāo)識(shí)觸發(fā)器名稱,用戶自行指定;
trigger_time標(biāo)識(shí)觸發(fā)時(shí)機(jī),用before和after替換;
trigger_event標(biāo)識(shí)觸發(fā)事件,用insert,update和delete替換;
tbl_name標(biāo)識(shí)建立觸發(fā)器的表名,即在哪張表上建立觸發(fā)器;
trigger_stmt是觸發(fā)器程序體;觸發(fā)器程序可以使用begin和end作為開始和結(jié)束,中間包含多條語(yǔ)句;
下面給出sfrd一個(gè)觸發(fā)器實(shí)例:
CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER trig_useracct_update
AFTER UPDATE
ON SF_User.useracct FOR EACH ROW
BEGIN
IF OLD.ulevelid = 10101 OR OLD.ulevelid = 10104 THEN
IF NEW.ulevelid = 10101 OR NEW.ulevelid = 10104 THEN
if NEW.ustatid != OLD.ustatid OR NEW.exbudget != OLD.exbudget THEN
INSERT into FC_Output.fcevent set type = 2, tabid = 1, level = 1, userid = NEW.userid, ustatid = NEW.ustatid, exbudget = NEW.exbudget;
end if;
ELSE
INSERT into FC_Output.fcevent set type = 1, tabid = 1, level = 1, userid = NEW.userid, ustatid = NEW.ustatid, exbudget = NEW.exbudget;
END IF;
END IF;
END;
上述觸發(fā)器實(shí)例使用了OLD關(guān)鍵字和NEW關(guān)鍵字。OLD和NEW可以引用觸發(fā)器所在表的某一列,在上述實(shí)例中,OLD.ulevelid表示表 SF_User.useracct修改之前ulevelid列的值,NEW.ulevelid表示表SF_User.useracct修改之后 ulevelid列的值。另外,如果是insert型觸發(fā)器,NEW.ulevelid也表示表SF_User.useracct新增行的 ulevelid列值;如果是delete型觸發(fā)器OLD.ulevelid也表示表SF_User.useracct刪除行的ulevelid列原值。
另外,OLD列是只讀的,NEW列則可以在觸發(fā)器程序中再次賦值。
上述實(shí)例也使用了IF,THEN ,ELSE,END IF等關(guān)鍵字。在觸發(fā)器程序體中,在beigin和end之間,可以使用順序,判斷,循環(huán)等語(yǔ)句,實(shí)現(xiàn)一般程序需要的邏輯功能。
查看觸發(fā)器。查看觸發(fā)器語(yǔ)法如下,如果知道觸發(fā)器所在數(shù)據(jù)庫(kù),以及觸發(fā)器名稱等具體信息:
SHOW TRIGGERS from SF_User like "usermaps%"; //查看SF_User庫(kù)上名稱和usermaps%匹配的觸發(fā)器
如果不了解觸發(fā)器的具體的信息,或者需要查看數(shù)據(jù)庫(kù)上所有觸發(fā)器,如下:
SHOW TRIGGERS; //查看所有觸發(fā)器
用上述方式查看觸發(fā)器可以看到數(shù)據(jù)庫(kù)的所有觸發(fā)器,不過(guò)如果一個(gè)庫(kù)上的觸發(fā)器太多,由于會(huì)刷屏,可能沒有辦法查看所有觸發(fā)器程序。這時(shí),可以采用如下方式:
Mysql中有一個(gè)information_schema.TRIGGERS表,存儲(chǔ)所有庫(kù)中的所有觸發(fā)器,desc information_schema. TRIGGERS,可以看到表結(jié)構(gòu):
+----------------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------+-------+
| TRIGGER_CATALOG | varchar(512) | YES | | NULL | |
| TRIGGER_SCHEMA | varchar(64) | NO | | | |
| TRIGGER_NAME | varchar(64) | NO | | | |
| EVENT_MANIPULATION | varchar(6) | NO | | | |
| EVENT_OBJECT_CATALOG | varchar(512) | YES | | NULL | |
| EVENT_OBJECT_SCHEMA | varchar(64) | NO | | | |
| EVENT_OBJECT_TABLE | varchar(64) | NO | | | |
| ACTION_ORDER | bigint(4) | NO | | 0 | |
| ACTION_CONDITION | longtext | YES | | NULL | |
| ACTION_STATEMENT | longtext | NO | | | |
| ACTION_ORIENTATION | varchar(9) | NO | | | |
| ACTION_TIMING | varchar(6) | NO | | | |
| ACTION_REFERENCE_OLD_TABLE | varchar(64) | YES | | NULL | |
| ACTION_REFERENCE_NEW_TABLE | varchar(64) | YES | | NULL | |
| ACTION_REFERENCE_OLD_ROW | varchar(3) | NO | | | |
| ACTION_REFERENCE_NEW_ROW | varchar(3) | NO | | | |
| CREATED | datetime | YES | | NULL | |
| SQL_MODE | longtext | NO | | | |
| DEFINER | longtext | NO | | | |
+----------------------------+--------------+------+-----+---------+-------+
這樣,用戶就可以按照自己的需要,查看觸發(fā)器,比如使用如下語(yǔ)句查看上述觸發(fā)器:
select * from information_schema. TRIGGERS where TRIGGER_NAME= 'trig_useracct_update'\G;
刪除觸發(fā)器。刪除觸發(fā)器語(yǔ)法如下:
DROP TRIGGER [schema_name.]trigger_name
2.2 Msyql觸發(fā)器的trigger_time和trigger_event
現(xiàn)在,重新注意到trigger_time和trigger_event,上文說(shuō)過(guò), trigger_time可以用before和after替換,表示觸發(fā)器程序的執(zhí)行在sql執(zhí)行的前還是后;trigger_event可以用 insert,update,delete替換,表示觸發(fā)器程序在什么類型的sql下會(huì)被觸發(fā)。
在一個(gè)表上最多建立6個(gè)觸發(fā)器,即1)before insert型,2)before update型,3)before delete型,4)after insert型,5)after update型,6)after delete型。
觸發(fā)器的一個(gè)限制是不能同時(shí)在一個(gè)表上建立2個(gè)相同類型的觸發(fā)器。這個(gè)限制的一個(gè)來(lái)源是觸發(fā)器程序體的“begin和end之間允許運(yùn)行多個(gè)語(yǔ)句”(摘自mysql使用手冊(cè))。
另外還有一點(diǎn)需要注意,msyql除了對(duì)insert,update,delete基本操作進(jìn)行定義外,還定義了load data和replace語(yǔ)句,而load data和replace語(yǔ)句也能引起上述6中類型的觸發(fā)器的觸發(fā)。
Load data語(yǔ)句用于將一個(gè)文件裝入到一個(gè)數(shù)據(jù)表中,相當(dāng)與一系列insert操作。replace語(yǔ)句一般來(lái)說(shuō)和insert語(yǔ)句很像,只是在表中有 primary key和unique索引時(shí),如果插入的數(shù)據(jù)和原來(lái)primary key和unique索引一致時(shí),會(huì)先刪除原來(lái)的數(shù)據(jù),然后增加一條新數(shù)據(jù);也就是說(shuō),一條replace sql有時(shí)候等價(jià)于一條insert sql,有時(shí)候等價(jià)于一條delete sql加上一條insert sql。即是:
? Insert型觸發(fā)器:可能通過(guò)insert語(yǔ)句,load data語(yǔ)句,replace語(yǔ)句觸發(fā);
? Update型觸發(fā)器:可能通過(guò)update語(yǔ)句觸發(fā);
? Delete型觸發(fā)器:可能通過(guò)delete語(yǔ)句,replace語(yǔ)句觸發(fā);
3 Mysql觸發(fā)器的執(zhí)行順序
先拋出觸發(fā)器相關(guān)的幾個(gè)問(wèn)題
3.1 如果before類型的觸發(fā)器程序執(zhí)行失敗,sql會(huì)執(zhí)行成功嗎?
實(shí)驗(yàn)如下:
1)在FC_Word.planinfo中建立before觸發(fā)器:
DELIMITER |
create trigger trigger_before_planinfo_update
before update
ON FC_Word.planinfo FOR EACH ROW
BEGIN
insert into FC_Output.abc (planid) values (New.planid);
END
|
2)查看:mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
3)執(zhí)行sql:
update planinfo set showprob=200 where planid=1; 觸發(fā)觸發(fā)器程序;
4)由于不存在FC_Output.abc,before觸發(fā)器執(zhí)行失敗,提示:
ERROR 1146 (42S02): Table 'FC_Output.abc' doesn't exist
5)再次查看:
mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
即修改sql未執(zhí)行成功。即如果before觸發(fā)器執(zhí)行失敗,sql也會(huì)執(zhí)行失敗。
3.2 如果sql執(zhí)行失敗,會(huì)執(zhí)行after類型的觸發(fā)器程序嗎?
實(shí)驗(yàn)如下:
1)在FC_Word.planinfo中建立after觸發(fā)器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
BEGIN
INSERT INTO FC_Output.fcevent set level = 2, type = 2, tabid = 5, userid = NEW.userid, planid = NEW.planid, planstat2 = NEW.planstat2, showprob = NEW.showprob, showrate = NEW.showrate, showfactor = NEW.showfactor, planmode = NEW.planmode;
END
|
2)查看觸發(fā)表:
mysql> select * from FC_Output.fcevent where planid=1;
Empty set (0.00 sec)
沒有planid=1的記錄
3)執(zhí)行sql:
mysql> update planinfo set showprob1=200 where planid=1;
4)由于不存在showprob1列,提示錯(cuò)誤:
ERROR 1054 (42S22): Unknown column 'showprob1' in 'field list'
5)再次查看觸發(fā)表:
mysql> select * from FC_Output.fcevent where planid=1;
Empty set (0.00 sec)
觸發(fā)表中沒有planid=1的記錄,sql在執(zhí)行失敗時(shí),after型觸發(fā)器不會(huì)執(zhí)行。
3.3 如果after類型的觸發(fā)器程序執(zhí)行失敗,sql會(huì)回滾嗎?
實(shí)驗(yàn)如下:
1)在FC_Word.planinfo中建立after觸發(fā)器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
BEGIN
insert into FC_Output.abc (planid) values (New.planid);
END
|
2)查看:mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
3)執(zhí)行sql:
update planinfo set showprob=200 where planid=1;觸發(fā)觸發(fā)器程序;
4)由于不存在FC_Output.abc,after觸發(fā)器執(zhí)行失敗,提示:
ERROR 1146 (42S02): Table 'FC_Output.abc' doesn't exist
5)再次查看:
mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
即修改sql未執(zhí)行成功。即如果after觸發(fā)器執(zhí)行失敗,sql會(huì)回滾。
這里需要說(shuō)明一下,上述實(shí)驗(yàn)所使用的mysql引擎是innodb,innodb引擎也是目前線上鳳巢系統(tǒng)、北斗系統(tǒng)以及哥倫布系統(tǒng)所使用的引擎,在 innodb上所建立的表是事務(wù)性表,也就是事務(wù)安全的。“對(duì)于事務(wù)性表,如果觸發(fā)程序失敗(以及由此導(dǎo)致的整個(gè)語(yǔ)句的失敗),該語(yǔ)句所執(zhí)行的所有更改將回滾。對(duì)于非事務(wù)性表,不能執(zhí)行這類回滾”(摘自mysql使用手冊(cè))。因而,即使語(yǔ)句失敗,失敗之前所作的任何更改依然有效,也就是說(shuō),對(duì)于 innodb引擎上的數(shù)據(jù)表,如果觸發(fā)器中的sql或引發(fā)觸發(fā)器的sql執(zhí)行失效,則事務(wù)回滾,所有操作會(huì)失效。
3.4 mysql觸發(fā)器程序執(zhí)行的順序
當(dāng)一個(gè)表既有before類型的觸發(fā)器,又有after類型的觸發(fā)器時(shí);當(dāng)一條sql語(yǔ)句涉及多個(gè)表的update時(shí),sql、觸發(fā)器的執(zhí)行順序經(jīng)過(guò)mysql源碼包裝過(guò),有時(shí)比較復(fù)雜。
可以先看一段mysql的源代碼,當(dāng)SQL中update多表的時(shí)候,Mysql的執(zhí)行過(guò)程如下(省去了無(wú)關(guān)代碼):
/* 遍歷要更新的所有表 */
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
org_updated = updated
/* 如果有 BEFORE 觸發(fā)器,則執(zhí)行;如果執(zhí)行失敗,跳到err2位置 */
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,TRG_ACTION_BEFORE, TRUE))
goto err2;
/*執(zhí)行更新,如果更新失敗,跳到err位置*/
if(local_error=table->file->update_row(table->record[1], table->record[0])))
goto err;
updated++; // 更新計(jì)數(shù)器
/* 如果有 AFTER 觸發(fā)器,則執(zhí)行;如果執(zhí)行失敗,跳到err2位置*/
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))
goto err2;
err:
{
/*標(biāo)志錯(cuò)誤信息,寫日志等*/
}
err2:
{
/*恢復(fù)執(zhí)行過(guò)的操作*/
check_opt_it.rewind();
/*如果執(zhí)行了更新,且表是有事務(wù)的,做標(biāo)志*/
if (updated != org_updated)
{
if (table->file->has_transactions())
transactional_tables= 1;
}
}
}
從上面代碼可以找到本章開始時(shí)拋出問(wèn)題的答案。
1) 如果before型觸發(fā)器執(zhí)行失敗,直接goto跳到err2位置,不會(huì)執(zhí)行后續(xù)sql語(yǔ)句;
2) 如果sql執(zhí)行失敗,直接goto跳到err位置,不會(huì)執(zhí)行或許的after型觸發(fā)器;
3) 如過(guò)after觸發(fā)器執(zhí)行失敗,goto到err2位置,恢復(fù)執(zhí)行過(guò)的操作,且在事務(wù)型的表上做標(biāo)記。
另外,在使用復(fù)雜的sql時(shí),由于有些復(fù)雜的sql是mysql自己定義的,所以存在不確定性,使用簡(jiǎn)單的sql比較可控。
4 Mysql觸發(fā)器在數(shù)據(jù)庫(kù)同步中的表現(xiàn)
4.1 觸發(fā)器運(yùn)行失敗時(shí),數(shù)據(jù)庫(kù)同步會(huì)失敗嗎?
有同步關(guān)系如下dbA?dbB。初始時(shí)同步正常。
1)在dbB上建立觸發(fā)器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
BEGIN
insert into FC_Output.abc (planid) values (New.planid);
END
|
2)在dbA上執(zhí)行sql,執(zhí)行成功;
mysql> update planinfo set showprob=200 where planid= 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
3)由于dbB上沒有FC_Output.abc表,觸發(fā)器會(huì)執(zhí)行失敗,這時(shí),檢查一下同步狀態(tài):
Slave_IO_Running: Yes
Slave_SQL_Running: NO
Last_Errno: 1146
Last_Error: Error 'Table 'FC_Output.abc' doesn't exist' on query. Default database: 'FC_Word'. Query: 'update planinfo set showprob=200 where planid= 1'
可以看到IO線程運(yùn)行正常,sql線程運(yùn)行失敗,并提示觸發(fā)器運(yùn)行失敗的錯(cuò)誤信息。
回憶一下3.1和3.3所述部分,無(wú)論是before部分的觸發(fā)器還是after類型的觸發(fā)器,對(duì)于innodb引擎,當(dāng)觸發(fā)器執(zhí)行失敗時(shí),相應(yīng)sql也會(huì)執(zhí)行失敗,所以數(shù)據(jù)庫(kù)同步也會(huì)失敗。
4.2 創(chuàng)建、刪除觸發(fā)器寫bin-log
創(chuàng)建和刪除觸發(fā)器的語(yǔ)句也會(huì)寫入bin-log里,所以也會(huì)如一般的insert,update,delete語(yǔ)句一樣同步到下游數(shù)據(jù)庫(kù)中,即上游創(chuàng)建觸發(fā)器,下游也會(huì)創(chuàng)建。
這里再引出兩個(gè)小問(wèn)題:有同步關(guān)系dbA?dbB,
1) 在dbA上創(chuàng)建一個(gè)觸發(fā)器,如果dbB上已經(jīng)有同表同類型的觸發(fā)器,同步狀態(tài)如何?
2) 在dbB上刪除一個(gè)觸發(fā)器,如果dbB上沒有對(duì)應(yīng)觸發(fā)器,同步狀態(tài)如何?
這兩個(gè)問(wèn)題可以類比同步中的insert語(yǔ)句和delete語(yǔ)句,答案就是
1) 同步失敗,因?yàn)椴辉试S重復(fù)創(chuàng)建同表同類型的觸發(fā)器;
2) 同步正常,因?yàn)閐rop一個(gè)不存在的觸發(fā)器,不影響運(yùn)行結(jié)果;
5 Mysql觸發(fā)器經(jīng)典案例
5.1 案例1 一條sql涉及多個(gè)表的update時(shí),觸發(fā)得到update之前的舊值
【現(xiàn)象】表test_info上建有觸發(fā)器如下:
CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER trig_test_info_update
AFTER UPDATE
ON FC_Word.test_info FOR EACH ROW
BEGIN
DECLARE tlevel INTEGER DEFAULT 0;
DECLARE ttype INTEGER DEFAULT 0;
SET tlevel = 4;
SET ttype = 33;
INSERT INTO TEST_Output.fcevent (te, le, uid, pid, uid, wid, bi, mbid, wl) SELECT ttype, tlevel, NEW.uid, NEW.pid, NEW.uid, NEW.wid, NEW.bi, NEW.mbid, wl FROM TEST_Word.wext2 where wid = NEW.wid;
/*。。。其余部分邏輯省略*/
END IF;
END;
這個(gè)觸發(fā)器程序有點(diǎn)長(zhǎng),可以單看飄黃的兩句,即更新操作滿足第一個(gè)條件執(zhí)行飄黃語(yǔ)句時(shí),觸發(fā)器的行為。觸發(fā)器是建立在test_info表上的,飄黃語(yǔ)句中可以看到,也需要查詢wext2表。
執(zhí)行如下sql1:
Update test_info a, wext2 b set a.th=(a.th+1), a.w4=(a.w4&8), b.wl=NULL where a.wid=b.wid and a.wid=142394379;
可以看到sql中既修改了test_info2表,同時(shí)修改了wext2表,程序原意是觸發(fā)得到wext2表wl字段修改后的新值(即NULL);不過(guò)實(shí)驗(yàn)得到,執(zhí)行上述sql后,觸發(fā)器程序查詢到的wurl是sql修改之前的舊值。
再執(zhí)行下面類似sql2:
Update wext2 a, test_info2 b set b.th=(b.th+1), b.w4=(b.w4&8), a.wl=NULL where a.wid=b.wid and a.wid=142394379;
實(shí)驗(yàn)的到,執(zhí)行上述sql后,觸發(fā)器程序查詢到的wurl是sql修改之后的新值。
【原因】原因當(dāng)然與sql中的別名a,b無(wú)關(guān),而是和wext2表和test_info表的書寫順序有關(guān)。如本文3.4部分所述,一條sql涉及多個(gè)表的 update操作時(shí),數(shù)據(jù)表字段、觸發(fā)器執(zhí)行順序是mysql源碼包裝過(guò)的。在執(zhí)行上述sql1時(shí),先執(zhí)行test_info的更新,然后是after觸發(fā)器,最后是wext2的更新,也就是說(shuō),在執(zhí)行after觸發(fā)器時(shí),wext2還沒有進(jìn)行更新,所以觸發(fā)得到的是舊值。而執(zhí)行sql2時(shí),先執(zhí)行 wext2更新,然后是test_info更新,最后是after觸發(fā)器,也就是說(shuō),在執(zhí)行after觸發(fā)器時(shí),wext2已經(jīng)更新完畢,所以出去得到的是新值。
引起上述現(xiàn)象是順序關(guān)系的,無(wú)論該表是否支持事務(wù)。在使用復(fù)雜的sql時(shí),由于有些復(fù)雜的sql是mysql自己定義的,所以存在不確定性,存在風(fēng)險(xiǎn),使用簡(jiǎn)單的sql比較可控。
5.2 案例2 mysql5.0.19版本修改表結(jié)構(gòu)后觸發(fā)器失效
【現(xiàn)象】userpref表上建有after類型觸發(fā)器,修改userpref表的外鍵關(guān)聯(lián)后,在userpref表中的新增記錄沒有觸發(fā)下來(lái),即觸發(fā)器失效。
【原因】mysql5.0.19修改表結(jié)構(gòu)是,觸發(fā)器消失。這是mysql5.0.19的一個(gè)bug,在創(chuàng)建觸發(fā)器時(shí),會(huì)把觸發(fā)器的內(nèi)容保存在 information_schema.TRIGGERS表中,同時(shí)在var目錄下創(chuàng)建觸發(fā)器的數(shù)據(jù)庫(kù)目錄下創(chuàng)建一個(gè)觸發(fā)器名稱為前綴,以TRN為后綴的文件,當(dāng)修改觸發(fā)器的表時(shí),information_schema.TRIGGERS表的內(nèi)容會(huì)刪除,導(dǎo)致觸發(fā)器消失。
在mysql5.0.45版本中,這個(gè)bug已經(jīng)被修復(fù)。Mysql5.0.45版本的觸發(fā)器,無(wú)論是修改表的索引、外鍵,還是改變表字段,觸發(fā)器都不會(huì)失效。
5.3 案例3 刪除數(shù)據(jù)表后觸發(fā)器失效
【現(xiàn)象】聯(lián)調(diào)環(huán)境中存在dbA?dbB,主庫(kù)dbA上沒有觸發(fā)器,在從庫(kù)dbB上的FC_Word.wnegative表,F(xiàn)C_Word.wbuget 表上建有觸發(fā)器;觸發(fā)器開始運(yùn)行正常,期間沒有對(duì)從庫(kù)的任何直接操作,有一日發(fā)現(xiàn)對(duì)wnegative表上的修改無(wú)法觸發(fā)。查看從庫(kù)狀態(tài),同步正常;用 select TRIGGER_NAME from information_schema.TRIGGERS發(fā)現(xiàn)wnegative表上的觸發(fā)器消失了;在var/FC_Word目錄下也沒有 wnegative的.TRN文件,wnegative表上的觸發(fā)器不見了。
【分析】查找dbB的查詢?nèi)罩荆l(fā)現(xiàn)有一條:
100223 18:27:45 135939 Query DROP TABLE IF EXISTS `wnegative`
135939 Query CREATE TABLE `wnegative` (
KEY `Index_wnegative_planid` (`planid`),
KEY `Index_wnegative_unitid` (`unitid`)
135939 Query /*!40000 ALTER TABLE `wnegative` DISABLE KEYS */
100223 18:27:46 135939 Query INSERT INTO `wnegative` VALUES (614,1,289026,2911155,1848481);
可以看到,在100223 18:27:45時(shí),刪除了表wnegative,緊接著有創(chuàng)建表wnegative;查找觸發(fā)表發(fā)現(xiàn),在100223 18:27:45時(shí)間后對(duì)wnegative的修改就沒有觸發(fā)了,而在這個(gè)之前對(duì)wnegative的修改是觸發(fā)正常的。故,懷疑對(duì)wnegative表的刪除使wnegative表上的觸發(fā)器也被刪除。對(duì)wnegative表的刪除是在主庫(kù)dbA上操作后,被同步到dbB上。
【原因】在刪除wnegative表時(shí),mysql同時(shí)刪除了wegative表上的觸發(fā)器。
可以通過(guò)下面實(shí)驗(yàn)證明上述猜測(cè):
1) 首先在wnegative建立after insert型觸發(fā)器;
2) 增加一條wnegative中記錄;
3) 查看結(jié)果發(fā)現(xiàn)觸發(fā)器正確觸發(fā);
4) 刪除wnegative表;
5) 使用select TRIGGER_NAME from information_schema.TRIGGERS查看所有觸發(fā)器,wnegative表上觸發(fā)器已經(jīng)不存在了;同時(shí)到var/FC_Word目錄下,對(duì)應(yīng)觸發(fā)器的.TRN文件也不存在了;
6) 重新創(chuàng)建wnegative表,并增加一條wnegative中記錄;沒有了wnegative表上觸發(fā)器,自然也不能觸發(fā)任何結(jié)果。
6 結(jié)束語(yǔ)
Mysql中的觸發(fā)器功能已經(jīng)在鳳巢系統(tǒng)的各個(gè)模塊中有廣泛應(yīng)用,究其細(xì)節(jié),還有很多值得注意的地方;本文建立在實(shí)驗(yàn)和案例的基礎(chǔ)上,數(shù)據(jù)庫(kù)基于線上系統(tǒng)使用的mysql5.0.45版本,分析了觸發(fā)器相關(guān)的一些特殊情況下msyql的處理方式。
(全文完)
1 背景:
x86平臺(tái)有完善的用戶態(tài)檢測(cè)內(nèi)存工具比如valgrind等,可以監(jiān)控程序運(yùn)行中詳細(xì)的內(nèi)存信息,從而精確定位內(nèi)存問(wèn)題。然而隨著新平臺(tái)的快速誕生(比如Tilera的TilePro64 CPU),這些工具不能被及時(shí)地移植,導(dǎo)致新平臺(tái)缺乏相應(yīng)的手段來(lái)定位內(nèi)存錯(cuò)誤,如內(nèi)存越界,泄漏等,而只能使用粗粒度的方法top,free 等指令觀察進(jìn)程的動(dòng)態(tài)內(nèi)存總額。其缺點(diǎn)是粒度太粗,而且內(nèi)存的總數(shù)變化有很多原因引起,在復(fù)雜的系統(tǒng)里,很難精確定位內(nèi)存問(wèn)題的根源,甚至?xí)﹫?bào)錯(cuò)報(bào),這嚴(yán)重影響了新平臺(tái)(如Tilera)開發(fā)與測(cè)試的效率。針對(duì)這個(gè)問(wèn)題,我們提出了一個(gè)通用的新平臺(tái)針對(duì)c/c++內(nèi)存錯(cuò)誤檢測(cè)框架。
該框架可適用于任何平臺(tái)。其通過(guò)重寫標(biāo)準(zhǔn)庫(kù)的內(nèi)存分配和釋放函數(shù)(如malloc, new, new[], free,delete,delete[]等), 以及維護(hù)一個(gè)全局的內(nèi)存分配map數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。重寫后的內(nèi)存分配比如my_malloc首先調(diào)用系統(tǒng)malloc功能,然后記錄每一次malloc執(zhí)行過(guò)程中的內(nèi)存操作信息(包括文件名、行號(hào)以及內(nèi)存尺寸,函數(shù)調(diào)用棧),以指針值為 key值,存進(jìn)維護(hù)的全局map表。而重寫的my_free則是根據(jù)傳入的指針值在 map 中查找相應(yīng)的數(shù)據(jù)項(xiàng)并將之刪除,而后調(diào)用系統(tǒng)的free 將指針?biāo)赶虻膬?nèi)存塊釋放。這樣當(dāng)程序退出的時(shí)候,map 中的剩余的數(shù)據(jù)項(xiàng)就是我們期望檢測(cè)的內(nèi)存泄漏信息。我們可以輸出泄漏內(nèi)存塊的詳細(xì)日志,比如文件名,行號(hào)等等。這將大大提高類似Tilera平臺(tái)的內(nèi)存問(wèn)題追查效率,提高開發(fā)和測(cè)試的速度和質(zhì)量。
2 基本原理:
1) 通過(guò)重寫非共享內(nèi)存分配釋放函數(shù)malloc, new, new[],free,delete,delete[]截獲 它們?cè)趫?zhí)行過(guò)程中的內(nèi)存操作信息。重載形式如下:
※ void* malloc( size_t nSize, char* pszFileName, int nLineNum )
※ void* new( size_t nSize, char* pszFileName, int nLineNum )
※ void* operator new[]( size_t nSize, char* pszFileName, int nLineNum )
※ void free( void *ptr )
※ void delete( void *ptr )
※ void operator delete[]( void *ptr )
2) 通過(guò)重寫共享內(nèi)存分配釋放函數(shù)mspace_malloc,mspace_free,重寫形式如下:
※ void* my_mspace_malloc( mspace msp,unsigned int Size, char* pszFileName, int nLineNum )
※ void my_mspace_free(mspace msp, void *ptr )
3) 我們對(duì)malloc, new, new[],mspace_malloc進(jìn)行了重載,參數(shù)包括size_t nSize、文件名和行號(hào),這里的文件名和行號(hào)就是這次malloc, new, new[],mspace_malloc操作符被調(diào)用時(shí)所在的文件名和行號(hào),這個(gè)信息將在發(fā)現(xiàn)內(nèi)存泄漏時(shí)輸出,以幫助定位泄漏具體位置。對(duì)于 free,delete,delete[],mspace_free參數(shù)為指針地址。
3 實(shí)例:
以My_malloc, My_free為例,重寫函數(shù)結(jié)構(gòu)如下:

1. 在重寫的my_malloc函數(shù)版本中,我們將調(diào)用malloc 的原始版本并將相應(yīng)的 size_t 參數(shù)傳入,然后,我們將malloc的原始版本返回的指針值以及該次分配所在的文件名和行號(hào)信息記錄下來(lái),這里采用STL 的 map數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),以指針值為 key 值,文件名,行號(hào)等信息作為一個(gè)結(jié)構(gòu)體是value值。
My_free重寫函數(shù)結(jié)構(gòu)如下:

2. 當(dāng)my_free 被調(diào)用時(shí),我們根據(jù)傳入的指針值在 map 中找到相應(yīng)的數(shù)據(jù)項(xiàng)并將之刪除,而后調(diào)用 free 將指針?biāo)赶虻膬?nèi)存塊釋放。這樣當(dāng)程序退出的時(shí)候,map 中的剩余的數(shù)據(jù)項(xiàng)就是我們企圖檢測(cè)的內(nèi)存泄漏信息。
4 實(shí)現(xiàn)關(guān)鍵點(diǎn):
1) 如何取得內(nèi)存分配代碼所在的文件名和行號(hào)?
利用 C 的預(yù)編譯宏 __FILE__ 和 __LINE__,這兩個(gè)宏將在編譯時(shí)在指定位置展開為該文件的文件名和該行的行號(hào)
2) 利用宏定義開關(guān)決定走普通分支還是內(nèi)存檢測(cè)分支?
#if defined( MEM_DEBUG )
#define malloc DEBUG_MALLOC
#define free DEBUG_FREE
#endif
3) 何時(shí)創(chuàng)建用于存儲(chǔ)內(nèi)存數(shù)據(jù)的 map 數(shù)據(jù)結(jié)構(gòu),如何管理,何時(shí)打印內(nèi)存泄漏信息?
設(shè)計(jì)一個(gè)類來(lái)封裝這個(gè) map 以及對(duì)它的插入刪除操作,然后構(gòu)造這個(gè)類的一個(gè)全局對(duì)象(appMemory),在全局對(duì)象(appMemory)的構(gòu)造函數(shù)中創(chuàng)建并初始化這個(gè)數(shù)據(jù)結(jié) 構(gòu),而在其析構(gòu)函數(shù)中對(duì)數(shù)據(jù)結(jié)構(gòu)中剩余數(shù)據(jù)進(jìn)行分析和輸出。new 中將調(diào)用這個(gè)全局對(duì)象的 insert 接口將指針、文件名、行號(hào)、內(nèi)存塊大小等信息以指針值為 key 記錄到 map 中,在delete 中調(diào)用 erase 接口將對(duì)應(yīng)指針值的 map 中的數(shù)據(jù)項(xiàng)刪除,同時(shí)對(duì) map 的訪問(wèn)需要進(jìn)行互斥同步,因?yàn)橥粫r(shí)間可能會(huì)有多個(gè)進(jìn)程進(jìn)行堆上的內(nèi)存操作。
4) 如何為非共享內(nèi)存申請(qǐng)map?如何為共享內(nèi)存申請(qǐng)map?
非共享內(nèi)存的map,對(duì)于多進(jìn)程則有多個(gè)map,可按(3)的方法處理。而對(duì)于共享內(nèi)存,可能A進(jìn)程申請(qǐng)到B進(jìn)程才釋放,但是每個(gè)進(jìn)程一個(gè)map,我們?nèi)呙柽@些每個(gè)map時(shí)就會(huì)出現(xiàn)誤報(bào)的現(xiàn)象,因此需要采取將map放入共享內(nèi)存方法:我們申請(qǐng)一塊共享內(nèi)存區(qū)域?yàn)閙ap,這個(gè)map對(duì)各進(jìn)程是共享的。當(dāng)程序中各進(jìn)程調(diào)用共享內(nèi)存時(shí),將各進(jìn)程分配的指針及文件名行號(hào)等詳細(xì)信息存進(jìn)這共享的map。程序結(jié)束時(shí),掃描該共享的map,就能得到未釋放的信息。將 map放入共享內(nèi)存使用c++標(biāo)準(zhǔn)庫(kù)時(shí)需要我們自己實(shí)現(xiàn)一個(gè)基于共享內(nèi)存的allocator,替換map默認(rèn)的allocator,在這個(gè)allocator中實(shí)現(xiàn)map的內(nèi)存分配方案。也可以使用boost庫(kù)(1.35以上版本),它增加了一個(gè)叫做boost::interprocess的庫(kù),具體可參考http://blog.cong.co/stl-alloc.html
5) 如何使用該工具?
內(nèi)存泄露檢測(cè)框架提供接口libmemck.h,內(nèi)容如下

在被測(cè)試程序里包含如下代碼即可使用

6) 何時(shí)如何捕獲信號(hào),生成leak文件?
定義一個(gè)全局的類得對(duì)象,在該類得構(gòu)造函數(shù)里通過(guò)signal函數(shù)捕獲SIGINT、SIGABRT、SIGFPE、SIGTERM信號(hào),當(dāng)捕獲到這些信號(hào)其中之一時(shí),開始掃描map并將map剩余信息寫入leak文件展示。
7) 對(duì)臨界資源的控制?
共享內(nèi)存的各進(jìn)程共享的map,各進(jìn)程間進(jìn)行讀寫操作需要加鎖,我們這里采用的是信號(hào)燈實(shí)現(xiàn)。
非共享內(nèi)存各個(gè)進(jìn)程對(duì)應(yīng)的map,在各進(jìn)程進(jìn)行插入刪除操作時(shí)也需要加鎖實(shí)現(xiàn)
8) 程序中malloc作為函數(shù)指針?
由于將原型malloc(size)重寫為my_malloc(size,__FILE__,__LINE__),這樣由于函數(shù)類型不一致,導(dǎo)致程序調(diào)用該工具時(shí)編譯無(wú)法通過(guò),真對(duì)這種情況的解決辦法為:重寫malloc(size)為my_malloc_p(size)這樣除了文件名和行號(hào)無(wú)法得知外,泄露的多少內(nèi)存可以報(bào)出。
轉(zhuǎn)自http://hi.baidu.com/baiduqa/blog/item/e4c991c5ef46e5c7d10060fb.html
下面是Jquery中AJAX參數(shù)詳細(xì)列表:
參數(shù)名
類型
描述
url
String
(默認(rèn): 當(dāng)前頁(yè)地址) 發(fā)送請(qǐng)求的地址。
type
String
(默認(rèn): "GET") 請(qǐng)求方式 ("POST" 或 "GET"), 默認(rèn)為 "GET"。注意:其它 HTTP 請(qǐng)求方法,如 PUT 和 DELETE 也可以使用,但僅部分瀏覽器支持。
timeout
Number
設(shè)置請(qǐng)求超時(shí)時(shí)間(毫秒)。此設(shè)置將覆蓋全局設(shè)置。
async
Boolean
(默認(rèn): true) 默認(rèn)設(shè)置下,所有請(qǐng)求均為異步請(qǐng)求。如果需要發(fā)送同步請(qǐng)求,請(qǐng)將此選項(xiàng)設(shè)置為 false。注意,同步請(qǐng)求將鎖住瀏覽器,用戶其它操作必須等待請(qǐng)求完成才可以執(zhí)行。
beforeSend
Function
發(fā)送請(qǐng)求前可修改 XMLHttpRequest 對(duì)象的函數(shù),如添加自定義 HTTP 頭。XMLHttpRequest 對(duì)象是唯一的參數(shù)。
function (XMLHttpRequest) { this; // the options for this ajax request }
cache
Boolean
(默認(rèn): true) jQuery 1.2 新功能,設(shè)置為 false 將不會(huì)從瀏覽器緩存中加載請(qǐng)求信息。
complete
Function
請(qǐng)求完成后回調(diào)函數(shù) (請(qǐng)求成功或失敗時(shí)均調(diào)用)。參數(shù): XMLHttpRequest 對(duì)象,成功信息字符串。
function (XMLHttpRequest, textStatus) { this; // the options for this ajax request }
contentType
String
(默認(rèn): "application/x-www-form-urlencoded") 發(fā)送信息至服務(wù)器時(shí)內(nèi)容編碼類型。默認(rèn)值適合大多數(shù)應(yīng)用場(chǎng)合。
data
Object,
String
發(fā)送到服務(wù)器的數(shù)據(jù)。將自動(dòng)轉(zhuǎn)換為請(qǐng)求字符串格式。GET 請(qǐng)求中將附加在 URL 后。查看 processData 選項(xiàng)說(shuō)明以禁止此自動(dòng)轉(zhuǎn)換。必須為 Key/Value 格式。如果為數(shù)組,jQuery 將自動(dòng)為不同值對(duì)應(yīng)同一個(gè)名稱。如 {foo:["bar1", "bar2"]} 轉(zhuǎn)換為 '&foo=bar1&foo=bar2'。
dataType
String
預(yù)期服務(wù)器返回的數(shù)據(jù)類型。如果不指定,jQuery 將自動(dòng)根據(jù) HTTP 包 MIME 信息返回 responseXML 或 responseText,并作為回調(diào)函數(shù)參數(shù)傳遞,可用值:
"xml": 返回 XML 文檔,可用 jQuery 處理。
"html": 返回純文本 HTML 信息;包含 script 元素。
"script": 返回純文本 JavaScript 代碼。不會(huì)自動(dòng)緩存結(jié)果。
"json": 返回 JSON 數(shù)據(jù) 。
"jsonp": JSONP 格式。使用 JSONP 形式調(diào)用函數(shù)時(shí),如 "myurl?callback=?" jQuery 將自動(dòng)替換 ? 為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)。
error
Function
(默認(rèn): 自動(dòng)判斷 (xml 或 html)) 請(qǐng)求失敗時(shí)將調(diào)用此方法。這個(gè)方法有三個(gè)參數(shù):XMLHttpRequest 對(duì)象,錯(cuò)誤信息,(可能)捕獲的錯(cuò)誤對(duì)象。
function (XMLHttpRequest, textStatus, errorThrown) { // 通常情況下textStatus和errorThown只有其中一個(gè)有值 this; // the options for this ajax request }
global
Boolean
(默認(rèn): true) 是否觸發(fā)全局 AJAX 事件。設(shè)置為 false 將不會(huì)觸發(fā)全局 AJAX 事件,如 ajaxStart 或 ajaxStop 。可用于控制不同的Ajax事件
ifModified
Boolean
(默認(rèn): false) 僅在服務(wù)器數(shù)據(jù)改變時(shí)獲取新數(shù)據(jù)。使用 HTTP 包 Last-Modified 頭信息判斷。
processData
Boolean
(默認(rèn): true) 默認(rèn)情況下,發(fā)送的數(shù)據(jù)將被轉(zhuǎn)換為對(duì)象(技術(shù)上講并非字符串) 以配合默認(rèn)內(nèi)容類型 "application/x-www-form-urlencoded"。如果要發(fā)送 DOM 樹信息或其它不希望轉(zhuǎn)換的信息,請(qǐng)?jiān)O(shè)置為 false。
success
Function
請(qǐng)求成功后回調(diào)函數(shù)。這個(gè)方法有兩個(gè)參數(shù):服務(wù)器返回?cái)?shù)據(jù),返回狀態(tài)
function (data, textStatus) { // data could be xmlDoc, jsonObj, html, text, etc... this; // the options for this ajax request }
代碼:$(document).ready(function() {
jQuery("#clearCac").click(function() {
jQuery.ajax({
url: "/Handle/Do.aspx",
type: "post",
data: { id: '0' },
dataType: "json",
success: function(msg) {
alert(msg);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
},
complete: function(XMLHttpRequest, textStatus) {
this; // 調(diào)用本次AJAX請(qǐng)求時(shí)傳遞的options參數(shù)
}
});
});
});
一、error:function (XMLHttpRequest, textStatus, errorThrown)
{
}
(默認(rèn): 自動(dòng)判斷 (xml 或 html)) 請(qǐng)求失敗時(shí)調(diào)用時(shí)間。參數(shù)有以下三個(gè):XMLHttpRequest 對(duì)象、錯(cuò)誤信息、(可選)捕獲的錯(cuò)誤對(duì)象。如果發(fā)生了錯(cuò)誤,錯(cuò)誤信息(第二個(gè)參數(shù))除了得到null之外,還可能是"timeout", "error", "notmodified" 和 "parsererror"。
textStatus:
"timeout", "error", "notmodified" 和 "parsererror"。
二、error事件返回的第一個(gè)參數(shù)XMLHttpRequest有一些有用的信息:
XMLHttpRequest.readyState:
狀態(tài)碼
0 - (未初始化)還沒有調(diào)用send()方法
1 - (載入)已調(diào)用send()方法,正在發(fā)送請(qǐng)求
2 - (載入完成)send()方法執(zhí)行完成,已經(jīng)接收到全部響應(yīng)內(nèi)容
3 - (交互)正在解析響應(yīng)內(nèi)容
4 - (完成)響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了
三、data:"{}", data為空也一定要傳"{}";不然返回的是xml格式的。并提示parsererror.
四、parsererror的異常和Header 類型也有關(guān)系。及編碼header('Content-type: text/html; charset=utf8');
五、XMLHttpRequest.status:
1xx-信息提示
這些狀態(tài)代碼表示臨時(shí)的響應(yīng)。客戶端在收到常規(guī)響應(yīng)之前,應(yīng)準(zhǔn)備接收一個(gè)或多個(gè)1xx響應(yīng)。
100-繼續(xù)。
101-切換協(xié)議。
2xx-成功
這類狀態(tài)代碼表明服務(wù)器成功地接受了客戶端請(qǐng)求。
200-確定。客戶端請(qǐng)求已成功。
201-已創(chuàng)建。
202-已接受。
203-非權(quán)威性信息。
204-無(wú)內(nèi)容。
205-重置內(nèi)容。
206-部分內(nèi)容。
3xx-重定向
客戶端瀏覽器必須采取更多操作來(lái)實(shí)現(xiàn)請(qǐng)求。例如,瀏覽器可能不得不請(qǐng)求服務(wù)器上的不同的頁(yè)面,或通過(guò)代理服務(wù)器重復(fù)該請(qǐng)求。
301-對(duì)象已永久移走,即永久重定向。
302-對(duì)象已臨時(shí)移動(dòng)。
304-未修改。
307-臨時(shí)重定向。
4xx-客戶端錯(cuò)誤
發(fā)生錯(cuò)誤,客戶端似乎有問(wèn)題。例如,客戶端請(qǐng)求不存在的頁(yè)面,客戶端未提供有效的身份驗(yàn)證信息。400-錯(cuò)誤的請(qǐng)求。
401-訪問(wèn)被拒絕。IIS定義了許多不同的401錯(cuò)誤,它們指明更為具體的錯(cuò)誤原因。這些具體的錯(cuò)誤代碼在瀏覽器中顯示,但不在IIS日志中顯示:
401.1-登錄失敗。
401.2-服務(wù)器配置導(dǎo)致登錄失敗。
401.3-由于ACL對(duì)資源的限制而未獲得授權(quán)。
401.4-篩選器授權(quán)失敗。
401.5-ISAPI/CGI應(yīng)用程序授權(quán)失敗。
401.7–訪問(wèn)被Web服務(wù)器上的URL授權(quán)策略拒絕。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
403-禁止訪問(wèn):IIS定義了許多不同的403錯(cuò)誤,它們指明更為具體的錯(cuò)誤原因:
403.1-執(zhí)行訪問(wèn)被禁止。
403.2-讀訪問(wèn)被禁止。
403.3-寫訪問(wèn)被禁止。
403.4-要求SSL。
403.5-要求SSL128。
403.6-IP地址被拒絕。
403.7-要求客戶端證書。
403.8-站點(diǎn)訪問(wèn)被拒絕。
403.9-用戶數(shù)過(guò)多。
403.10-配置無(wú)效。
403.11-密碼更改。
403.12-拒絕訪問(wèn)映射表。
403.13-客戶端證書被吊銷。
403.14-拒絕目錄列表。
403.15-超出客戶端訪問(wèn)許可。
403.16-客戶端證書不受信任或無(wú)效。
403.17-客戶端證書已過(guò)期或尚未生效。
403.18-在當(dāng)前的應(yīng)用程序池中不能執(zhí)行所請(qǐng)求的URL。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
403.19-不能為這個(gè)應(yīng)用程序池中的客戶端執(zhí)行CGI。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
403.20-Passport登錄失敗。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
404-未找到。
404.0-(無(wú))–沒有找到文件或目錄。
404.1-無(wú)法在所請(qǐng)求的端口上訪問(wèn)Web站點(diǎn)。
404.2-Web服務(wù)擴(kuò)展鎖定策略阻止本請(qǐng)求。
404.3-MIME映射策略阻止本請(qǐng)求。
405-用來(lái)訪問(wèn)本頁(yè)面的HTTP謂詞不被允許(方法不被允許)
406-客戶端瀏覽器不接受所請(qǐng)求頁(yè)面的MIME類型。
407-要求進(jìn)行代理身份驗(yàn)證。
412-前提條件失敗。
413–請(qǐng)求實(shí)體太大。
414-請(qǐng)求URI太長(zhǎng)。
415–不支持的媒體類型。
416–所請(qǐng)求的范圍無(wú)法滿足。
417–執(zhí)行失敗。
423–鎖定的錯(cuò)誤。
5xx-服務(wù)器錯(cuò)誤
服務(wù)器由于遇到錯(cuò)誤而不能完成該請(qǐng)求。
500-內(nèi)部服務(wù)器錯(cuò)誤。
500.12-應(yīng)用程序正忙于在Web服務(wù)器上重新啟動(dòng)。
500.13-Web服務(wù)器太忙。
500.15-不允許直接請(qǐng)求Global.asa。
500.16–UNC授權(quán)憑據(jù)不正確。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
500.18–URL授權(quán)存儲(chǔ)不能打開。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
500.100-內(nèi)部ASP錯(cuò)誤。
501-頁(yè)眉值指定了未實(shí)現(xiàn)的配置。
502-Web服務(wù)器用作網(wǎng)關(guān)或代理服務(wù)器時(shí)收到了無(wú)效響應(yīng)。
502.1-CGI應(yīng)用程序超時(shí)。
502.2-CGI應(yīng)用程序出錯(cuò)。application.
503-服務(wù)不可用。這個(gè)錯(cuò)誤代碼為IIS6.0所專用。
504-網(wǎng)關(guān)超時(shí)。
505-HTTP版本不受支持。
FTP
1xx-肯定的初步答復(fù)
這些狀態(tài)代碼指示一項(xiàng)操作已經(jīng)成功開始,但客戶端希望在繼續(xù)操作新命令前得到另一個(gè)答復(fù)。
110重新啟動(dòng)標(biāo)記答復(fù)。
120服務(wù)已就緒,在nnn分鐘后開始。
125數(shù)據(jù)連接已打開,正在開始傳輸。
150文件狀態(tài)正常,準(zhǔn)備打開數(shù)據(jù)連接。
2xx-肯定的完成答復(fù)
一項(xiàng)操作已經(jīng)成功完成。客戶端可以執(zhí)行新命令。200命令確定。
202未執(zhí)行命令,站點(diǎn)上的命令過(guò)多。
211系統(tǒng)狀態(tài),或系統(tǒng)幫助答復(fù)。
212目錄狀態(tài)。
213文件狀態(tài)。
214幫助消息。
215NAME系統(tǒng)類型,其中,NAME是AssignedNumbers文檔中所列的正式系統(tǒng)名稱。
220服務(wù)就緒,可以執(zhí)行新用戶的請(qǐng)求。
221服務(wù)關(guān)閉控制連接。如果適當(dāng),請(qǐng)注銷。
225數(shù)據(jù)連接打開,沒有進(jìn)行中的傳輸。
226關(guān)閉數(shù)據(jù)連接。請(qǐng)求的文件操作已成功(例如,傳輸文件或放棄文件)。
227進(jìn)入被動(dòng)模式(h1,h2,h3,h4,p1,p2)。
230用戶已登錄,繼續(xù)進(jìn)行。
250請(qǐng)求的文件操作正確,已完成。
257已創(chuàng)建“PATHNAME”。
3xx-肯定的中間答復(fù)
該命令已成功,但服務(wù)器需要更多來(lái)自客戶端的信息以完成對(duì)請(qǐng)求的處理。331用戶名正確,需要密碼。
332需要登錄帳戶。
350請(qǐng)求的文件操作正在等待進(jìn)一步的信息。
4xx-瞬態(tài)否定的完成答復(fù)
該命令不成功,但錯(cuò)誤是暫時(shí)的。如果客戶端重試命令,可能會(huì)執(zhí)行成功。421服務(wù)不可用,正在關(guān)閉控制連接。如果服務(wù)確定它必須關(guān)閉,將向任何命令發(fā)送這一應(yīng)答。
425無(wú)法打開數(shù)據(jù)連接。
426Connectionclosed;transferaborted.
450未執(zhí)行請(qǐng)求的文件操作。文件不可用(例如,文件繁忙)。
451請(qǐng)求的操作異常終止:正在處理本地錯(cuò)誤。
452未執(zhí)行請(qǐng)求的操作。系統(tǒng)存儲(chǔ)空間不夠。
5xx-永久性否定的完成答復(fù)
該命令不成功,錯(cuò)誤是永久性的。如果客戶端重試命令,將再次出現(xiàn)同樣的錯(cuò)誤。500語(yǔ)法錯(cuò)誤,命令無(wú)法識(shí)別。這可能包括諸如命令行太長(zhǎng)之類的錯(cuò)誤。
501在參數(shù)中有語(yǔ)法錯(cuò)誤。
502未執(zhí)行命令。
503錯(cuò)誤的命令序列。
504未執(zhí)行該參數(shù)的命令。
530未登錄。
532存儲(chǔ)文件需要帳戶。
550未執(zhí)行請(qǐng)求的操作。文件不可用(例如,未找到文件,沒有訪問(wèn)權(quán)限)。
551請(qǐng)求的操作異常終止:未知的頁(yè)面類型。
552請(qǐng)求的文件操作異常終止:超出存儲(chǔ)分配(對(duì)于當(dāng)前目錄或數(shù)據(jù)集)。
553未執(zhí)行請(qǐng)求的操作。不允許的文件名。
本篇文章來(lái)源于 Linux公社網(wǎng)站(www.linuxidc.com) 原文鏈接:http://www.linuxidc.com/Linux/2011-11/47495.htm