- 18.2.1 MySQL server has gone away有關Lost connection to server during query的錯誤。
對MySQL server has gone away錯誤最常見的原因是伺服器逾時了並且關閉了串連。預設地,如果沒有事情發生,伺服器在 8個小時後關閉串連。你可在啟動mysqld時通過設定wait_timeout變數改變時間限制。你可以通過執行mysqladmin version並且檢驗正常啟動並執行時間來檢查MySQL還沒死掉。如果你有一個指令碼,你只須再發出查詢讓客護進行一次自動的重新串連。在這種請下,你通常能獲得下列錯誤碼(你得到的是OS相關的):
CR_SERVER_GONE_ERROR 客戶不能發送一個問題給伺服器。CR_SERVER_LOST 當寫伺服器時,客戶沒有出錯,但是它沒有得到對問題的一個完整的答案(或任何答案)。
如 果你向伺服器發送不正確的或太大的查詢,你也可能得到這些錯誤。如果mysqld得到一個太大或不正常的包,它認為客戶出錯了並關閉串連。如果你需要較大 的查詢(例如,如果你正在處理較大的BLOB列),你可以使用-O max_allowed_packet=#選項(預設1M)啟動mysqld以增加查詢限制。多餘的記憶體按需分配,這樣mysqld只有在你發出較大差詢 時或mysqld必須返回較大的結果行時,才使用更多的記憶體!
MySQL 4.0.21 使用注意事項
1、max_allowed_packet = 16M,預設為1M這涉及BLOB等最大,通常要修改。
2、沒有仔細看下面這段,這在MySQL的manual.html中有。建表時要用LONGBLOB 和LONGTEXT 。BLOB TEXT
A BLOB or TEXT column with a maximum length of 65,535 (2^16 -1) characters.
MEDIUMBLOB MEDIUMTEXT
A BLOB or TEXT column with a maximum length of 16,777,215 (2^24 - 1) characters.
LONGBLOB LONGTEXT
A BLOB or TEXT column with a maximum length of 4,294,967,295 or 4GB (2^32 - 1) characters.
3、中文問題,MySQL伺服器就是預設的latin1編碼,不用任何設定。在windows中文版上,linux上沒有測試過。資料庫驅動 com.mysql.jdbc.Driver (org.gjt.mm.mysql.Driver用本方法無效)
jdbc:mysql://localhost/risenet?useUnicode=true&characterEncoding=gb2312
在xml中不要直接使用“&”,需要使用XML轉意字元:&
- 18.2.2 Can’t connect to [local] MySQL server錯誤
一 個MySQL客戶可以兩種不同的方式串連mysqld伺服器:Unix通訊端,它通過在檔案系統中的一個檔案(預設“/tmp /mysqld.sock”)進行串連;或TCP/IP,它通過一個連接埠號碼串連。Unix通訊端比TCP/IP更快,但是只有用在串連同一台電腦上的服 務器。如果你不指定主機名稱或如果你指定特殊的主機名稱localhost,使用Unix通訊端。錯誤(2002)Can’t connect to ...通常意味著沒有一個MySQL伺服器運行在系統上或當試圖串連mysqld伺服器時,你正在使用一個錯誤的通訊端檔案或TCP/IP連接埠。由檢查(使用ps)在你的伺服器上有一個名為mysqld的進程啟動!如果沒有任何mysqld過程,你應該啟動一個。見4.15.2 啟動MySQL伺服器的問題。如果一個mysqld過程正在運行,你可以通過嘗試這些不同的串連來檢查伺服器(當然,連接埠號碼和通訊端路徑名可能在你的安裝中是不同的):
shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h ’ip for your host’ version
shell> mysqladmin --socket=/tmp/mysql.sock version
注意hostname命令使用反引號“`”而非正引號“’”;這些導致hostname輸出(即,當前主機名稱)被代替進mysqladmin命令中。這是可能造成Can’t connect to local MySQL server錯誤的一些原因:mysqld不在運行。你 正在使用MIT-pthreads的一個系統上運行。如果正在運行在一個沒有原生線程的系統上,mysqld使用 MIT-pthreads 軟體包。見4.2 由MySQL支援的作業系統。然而,MIT-pthreads不支援Unix通訊端,因此當與伺服器串連時,在這樣一個系統上,你總是必須明確地指定主機 名。試試使用這個命令檢查到伺服器的串連:
shell> mysqladmin -h `hostname` version
某 人刪除了mysqld使用的Unix通訊端(預設“/tmp/mysqld.sock”)。你可能有一個cron任務刪除了MySQL通訊端(例如,一個 把舊檔案從“/tmp”目錄中刪除的任務)。你總是可以運行mysqladmin version並且檢查mysqladmin正在試圖使用的通訊端確實存在。在這種情況下,修複方法是刪除cron任務而不刪除“mysqld.sock 或將通訊端放在其他地方。你能用這個命令在MySQL配置時指定一個不同的通訊端地點:
shell> ./configure --with-unix-socket-path=/path/to/socket
你 也可以使用--socket=/path/to/socket選項啟動safe_mysqld和在啟動你的MySQL客戶前設定環境變數 MYSQL_UNIX_PORT為通訊端路徑名。你可用--socket=/path/to/socket選項啟動mysqld伺服器。如果你改變了服務 器的通訊端路徑名,你也必須通知MySQL客戶關於新路徑的情況。你可以通過設定環境變數MYSQL_UNIX_PORT為通訊端路徑名或由提供通訊端路 徑名作為客戶的參數做到。你可用這個命令測試通訊端:
shell> mysqladmin --socket=/path/to/socket version
你正在使用 Linux和線程已經死了(核心傾倒了)。在這種情況中,你必須殺死其它mysqld線程(例如在啟動一個新的MySQL伺服器之前,可以用mysql_zap指令碼)。見18.1 如果MySQL總是崩潰怎麼辦。如果你得到錯誤Can’t connect to MySQL server on some_hostname,你可以嘗試下列步驟找出問題是什麼:通過執行telnet your-host-name tcp-ip-port-number並且按幾次斷行符號來檢查伺服器是否正常運行。如果有一個MySQL運行在這個連接埠上,你應該得到一個包含正在啟動並執行 MySQL伺服器的版本號碼的應答。如果你得到類似於telnet: Unable to connect to remote host: Connection refused的一個錯誤,那麼沒有伺服器在使用的連接埠上運行。嘗試串連本地機器上的mysqld守護進程,並用mysqladmin variables檢查mysqld被配置使用的TCP/IP連接埠(變數port)。檢查你的mysqld伺服器沒有用--skip-networking選項啟動。
- 18.2.3 Host ’...’ is blocked錯誤
如果你得到象這樣的一個錯誤:
Host ’hostname’ is blocked because of many connection errors.
Unblock with ’mysqladmin flush-hosts’
這 意味著,mysqld已經得到了大量(max_connect_errors)的主機’hostname’的在中途被中斷了的串連請求。在 max_connect_errors次失敗請求後,mysqld認定出錯了(象來字一個駭客的攻擊),並且阻止該網站進一步的串連,直到某人執行命令 mysqladmin flush-hosts。預設地,mysqld在10個串連錯誤後阻塞一台主機。你可以通過象這樣啟動伺服器很容易地調整它:
shell> safe_mysqld -O max_connect_errors=10000 &
注意,對給定的主機,如果得到這條錯誤訊息,你應該首先檢查該主機的TCP/IP串連有沒有問題。如果你的TCP/IP串連不在運行,
增加max_connect_errors變數的值對你也不會有協助!
- 18.2.4 Too many connections錯誤
如果在你試土串連MySQL時,你得到錯誤Too many connections,這意味著已經有max_connections個客戶串連了mysqld伺服器。
如果你需要比預設(100)更多的串連,那麼你應該重啟mysqld,用更大的 max_connections 變數值。
注 意,mysqld實際上允許(max_connections+1)個客戶串連。最後一個串連是為一個用Process許可權的使用者保留的。通過不把這個權 限給一般使用者(他們不應該需要它),有這個許可權一個管理員可以登入並且使用SHOW PROCESSLIST找出什麼可能出錯。見7.21 SHOW句法(得到表,列的資訊)。
如果你發出查詢並且得到類似於下面的錯誤:
mysql: Out of memory at line 42, ’malloc.c’
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory
注意,錯誤指向了MySQL客戶mysql。這個錯誤的原因很簡單,客戶沒有足夠的記憶體儲存全部結果。
為了修正這個問題,首先檢查你的查詢是否正確。它應該返回這麼多的行,這合理嗎?如果是這樣,
你可以使用mysql --quick,它使用mysql_use_result()檢索結果集合。這將較少的負擔放在了用戶端(只是伺服器更多)。
- 18.2.6 Packet too large錯誤
當一個MySQL客戶或mysqld伺服器得到一個比max_allowed_packet個位元組長的包,它發出一個Packet too large錯誤並終止串連。如果你正在使用mysql客戶,你可以通過用mysql --set-variable=max_allowed_packet=8M指定一個更大的緩衝區來啟動客戶程式。如 果你正在使用不允許你指定最大包大小的其他客戶(例如 DBI),你需要在你啟動伺服器時設定包大小。你可以使用mysqld的命令列選項設定max_allowed_packet為一個更大的尺寸。例如,如 果你正期望將一個全長的BLOB存入一張表中,你將需要用--set-variable=max_allowed_packet=24M選項來啟動服務 器。
- 18.2.7 The table is full錯誤
這個錯誤發生在記憶體暫存資料表變得比 tmp_table_size位元組大時。為了避免這個問題,你可以使用mysqld的-O tmp_table_size=#選項來增加暫存資料表的大小,或在你發出有疑問的查詢之前使用SQL選項SQL_BIG_TABLES。見7.25 SET OPTION句法。你也可以使用--big-tables選項啟動mysqld。這與為所有查詢使用SQL_BIG_TABLES完全相同。
- 18.2.8 Commands out of sync in client錯誤
如果你在你的客戶代碼中得到Commands out of sync; You can’t run this command now,你正在以錯誤的次序調用客戶函數!
這可能發生,例如,如果你正在使用mysql_use_result()並且在你已經調用了mysql_free_result()之前試圖執行新查詢。
如 果你在mysql_use_result()或mysql_store_result()之間試圖執行返回資料的2個查詢,它也可能發生。
如果你得到下列錯誤:
Found wrong password for user: ’some_user@some_host’; Ignoring user
這意味著在mysqld啟動時或在它再次裝載許可權表時,它在user表中找到了一個有一個無效口令的條目。
結果,條目簡單地被許可權系統忽略。可能導致這個問題的原因和修正:
你可能正在運行一個有一個老的user表的新版本mysqld。你可以通過執行mysqlshow mysql user看看口令欄位是否少於 16個字元來檢查它。如果是這樣,你可以通過運行scripts/add_long_password指令碼改正這種情況。使用者有一個老式的口令(8個字元長)並且你沒使用--old-protocol選項啟動mysqld。用一個新口令更新在user表中的使用者或用--old-protocol重啟mysqld。你沒有使用PASSWORD()函數在在user表中指定了一個口令。使用mysql以一個新口令更新在user表中的使用者。確保使用PASSWORD()函數:
mysql> update user set password=PASSWORD(’your password’) where user=’XXX’;
- 18.2.10 Table ’xxx’ doesn’t exist錯誤
如果你得到錯誤Table ’xxx’ doesn’t exist或Can’t find file: ’xxx’ (errno: 2),這意味著在當前資料庫中沒有名為xxx的表存在。
注意,因為MySQL使用目錄和檔案儲存體資料庫和表,資料庫和表名件是區分大小寫!(在Win32上,資料庫和表名不是區分大小寫,但是在查詢中對所有表的引用必須使用相同的大小寫!)
你可以用SHOW TABLES檢查你在當前資料庫中有哪個表。見7.21 SHOW句法(得到表、列的資訊)。
當出現一個磁碟溢出的情況時,MySQL做下列事情:
它每分鐘檢查一次看是否有足夠空間寫入當前行。如果有足夠的空間,它繼續好像發生什麼事情。每6分鐘它將有關磁碟溢出的警告寫入記錄檔。
為了緩和這個問題,你可以採取下列行動:繼續,你只需釋放足夠的空閑磁碟空間以便插入所有記錄。放棄線程,你必鬚髮一個mysqladmin kill到線程。在下一次檢查磁碟時,線程將被放棄(在1分鐘內)。注意,其他線程可能正在等待引起“磁碟溢出”條件的表。如果你有幾個“鎖定的”的線程,殺死正在等待磁碟溢出條件的那個線程將允許其他線程繼續。
一般地,mysql客戶被互動性地使用,象這樣:
shell> mysql database
然而,也可以把你的SQL命令放在一個檔案中並且告訴mysql從該檔案讀取其輸入。要想這樣做,
創造一個文字檔“text_file”,它包含你想要執行的命令。然後如下那樣調用mysql:
shell> mysql database < text_file
你也能啟動有一個USE db_name語句的文字檔。在這種情況下,在命令列上指定資料庫名是不必要的:
shell> mysql < text_file
見12.1 不同的MySQL程式概述。
MySQL 使用TMPDIR環境變數的值作為儲存臨時檔案的目錄的路徑名。如果你沒有設定TMPDIR,MySQL使用系統預設值,它通常是“/tmp”或“ /usr/tmp”。如果包含你的臨時檔案目錄的檔案系統太小,你應該編輯safe_mysqld設定TMPDIR指向你有足夠空間的一個檔案系統!你也 可以使用mysqld的--tmpdir選項目設定臨時目錄。MySQL以“隱含檔案”建立所有臨時檔案。這保證了如果mysqld被終止,臨時檔案也將被刪除。使用隱含檔案的缺點是你將看不到一個大的臨時檔案填滿了臨時檔案目錄所在的檔案系統。當排序(ORDER BY或GROUP BY)時,MySQL通常使用一個或兩個臨時檔案。最大磁碟空間需求是:
(儲存東西的長度 + sizeof (資料庫指標))
* 匹配的行數
* 2
sizeof(資料庫指標)通常是4,但是在未來對確實很大的表可能增加。
對一些SELECT查詢,MySQL也建立臨時SQL表。這些沒被隱含且有“SQL_*”格式的名字。
ALTER TABLE和OPTIMIZE TABLE在原資料庫表的同一個目錄中建立一張暫存資料表。
- 18.6 怎樣保護“/tmp/mysql.sock ”不被刪除
如果你有這個問題,事實上任何人可以刪除MySQL通訊通訊端“/tmp/mysql.sock”,在Unix的大多數版本上,你能通過為其設定sticky(t)位來保護你的“/tmp”檔案系統。作為root登入並且做下列事情:
shell> chmod +t /tmp
這將保護你的“/tmp”檔案系統使得檔案僅能由他們的所有者或超級使用者(root)刪除。
你能執行ls -ld /tmp檢查sticky位是否被設定,如果最後一位許可位是t,該位被設定了。
見6.6 許可權系統如何工作。並且特別要看6.13 引起Access denied錯誤的原因。
MySQL伺服器mysqld能被任何使用者啟動並運行。為了將mysqld改由Unix使用者user_name來運行,你必須做下列事情:
如果它正在運行,停止伺服器(使用mysqladmin shutdown)。
改變資料庫目錄和檔案以便user_name有許可權讀和寫檔案(你可能需要作為Unix的root使用者才能做到):
shell> chown -R user_name /path/to/mysql/datadir
如果在MySQL資料目錄中的目錄或檔案是符號連結,你也將需要順著那些連結並改變他們指向的目錄和檔案。chown -R不能跟隨符號連結。
以user_name使用者啟動伺服器,或如果你正在使用MySQL 3.22或以後版本,以Unix root使用者啟動mysqld並使用--user=user_name選項,mysqld將在接受任何串連之前切換到以Unix user_name使用者運行。如果在系統被重新啟動時,你使用mysql.server指令碼啟動mysqld,你應該編輯mysql.server用su以使用者user_name運行mysqld,或使用--user選項調用mysqld。(不改變safe_mysqld是必要的。)現在,你的mysqld進程應該正在作為Unix使用者user_name運行,並運行完好。儘管有一件事情沒有變化:許可權表的內容。預設 地(就在運行了指令碼mysql_install_db安裝的許可權表後),MySQL使用者root是唯一有存取mysql資料庫或建立或拋棄資料庫許可權的用 戶。除非你改變了那些許可權,否則他們仍然保持。當你作為一個Unix使用者而不是root登入時,這不應該阻止你作為MySQL root使用者來存取MySQL;只要為客戶程式指定-u root的選項。注意通過在命令列上提供-u root,作為root存取MySQL,與作為Unix root使用者或其他Unix使用者運行MySQL沒有關係。MySQL的存取許可權和使用者名稱與Unix使用者名稱字是完全分開的。唯一與Unix使用者名稱有關的是, 如果當你調用一個客戶程式時,你不提供一個-u選項,客戶將試圖使用你的Unix登入名稱作為你的MySQL使用者名稱進行串連。如果你的Unix機器本身不安全,你可能應該至少在存取表中為MySQL root使用者放上一個口令。否則,在那台機器上有一個帳號的任何使用者能運行mysql -u root db_name並且做他喜歡做的任何事情。
如果你忘記了MySQL的root使用者的口令,你可以用下列過程恢複它。
通過發送一個kill(不是kill -9)到mysqld伺服器來關閉mysqld伺服器。pid 被儲存在一個.pid檔案中,通常在MySQL資料庫目錄中:
kill `cat /mysql-data-directory/hostname.pid`
你必須是一個UNIX root使用者或運行伺服器的相同使用者做這個。
使用--skip-grant-tables選項重啟mysqld。
用mysql -h hostname mysql串連mysqld伺服器並且用一條GRANT命令改變口令。見7.26 GRANT和REVOKE句法。你也可以用mysqladmin -h hostname -u user password ’new password’ 進行。用mysqladmin -h hostname flush-privileges或用SQL命令FLUSH PRIVILEGES來裝載許可權表。
如果你有與檔案許可有關的問題,例如,如果當你建立一張表時,mysql發出下列錯誤訊息:
ERROR: Can’t find file: ’path/with/filename.frm’ (Errcode: 13)
那麼可能是在mysqld啟動時,環境變數UMASK可能設定不正確。預設的umask值是0660。你可以如下啟動safe_mysqld改變其行為:
shell> UMASK=384 # = 600 in octal
shell> export UMASK
shell> /path/to/safe_mysqld &
如 果你從MySQL得到ERROR ’...’ not found (errno: 23), Can’t open file: ... (errno: 24)或任何其他有errno 23或errno 24的錯誤,它意味著,你沒有為MySQL分配足夠的檔案描述符。你能使用perror公用程式得到錯誤號碼含義是什麼的描述:
shell> perror 23
File table overflow
shell> perror 24
Too many open files
這 裡的問題是mysqld正在試圖同時保持開啟太多的檔案。你也可以告訴mysqld一次不開啟那麼多的檔案,或增加mysqld可得到的檔案描述符數量。 為了告訴mysqld一次保持開啟更少的檔案,你可以通過使用safe_mysqld的-O table_cache=32選項(預設值是64)使表緩衝更小。減小max_connections值也將減少開啟檔案的數量(預設值是90)。要想改變mysqld可用的檔案描述符數量,修改safe_mysqld指令碼。指令碼中有一條注釋了的行ulimit -n 256。你可以刪除’#’字元來去掉該行的注釋,並且改變數字256改變為mysqld可用的檔案描述符的數量。ulimit 能增加檔案描述符的數量,但是只能到作業系統強加的限制。如果你需要增加每個進程可用的檔案描述符數量的OS限制,參見你的作業系統文檔。注意,如果你運 行tcsh外殼,ulimit將不工作!當你請求當前限制時,tcsh也將報告不正確的值!在這種情況下,你應該用sh啟動safe_mysqld!
一個DATE值的格式是’YYYY-MM-DD’。根據ANSI SQL,不允許其他格式。你應該在UPDATE運算式和SELECT語句的WHERE子句中使用這個格式。例如:mysql> SELECT * FROM tbl_name WHERE date >= ’1997-05-05’;
為 了方便,如果日期用在數字上下文,MySQL自動變換一個日期到一個數字(並且反過來也如此)。當更新時和將一個日期與TIMESTAMP、DATE或 DATETIME列比較的一個WHERE子句中,也是足夠靈活以允許一種“寬鬆”的字串格式。(寬鬆格式意味著任何標點字元用作在組件之間的分割符。例 如,’1998-08-15’和’1998#08#15’是等價的。)MySQL也能變換不包含分割符的一個字串(例如 ’19980815’),如果它作為一個日期說得通。特殊日期’0000-00-00’可以作為’0000-00-00’被儲存和檢索。當通過 MyODBC使用一個’0000-00-00’日期時,在MyODBC 2.50.12和以上版本,它將自動被轉換為NULL,因為ODBC不能處理這種日期。
因為MySQL實行了上述的變換,下列語句可以工作:
mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES (’19970505’);
mysql> INSERT INTO tbl_name (idate) VALUES (’97-05-05’);
mysql> INSERT INTO tbl_name (idate) VALUES (’1997.05.05’);
mysql> INSERT INTO tbl_name (idate) VALUES (’1997 05 05’);
mysql> INSERT INTO tbl_name (idate) VALUES (’0000-00-00’);
mysql> SELECT idate FROM tbl_name WHERE idate >= ’1997-05-05’;
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= ’19970505’;
然而,下列將不工作:
mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,’19970505’)=0;
STRCMP()是字串函數,因此它將idate轉換為一個字串並且實施字串比較。它不將’19970505’轉換為一個日期並實施日期比較。
注意,MySQL不檢查日期是否正確。如果你儲存一個不正確的日期,例如’1998-2-31’,錯誤的日期將被儲存。如果日期不能被變換到任何合理的值,在DATE欄位中儲存一個0。這主要是一個速度問題並且我們認為檢查日期是應用程式的責任,而不伺服器。
如果你有一個問題,SELECT NOW()以GMT時間傳回值而不是你的本地時間,你必須設定TZ環境變數為你的當前時區。這應該在伺服器啟動並執行環境進行,例如在safe_mysqld或mysql.server中。
缺 省地,MySQL搜尋是大小寫不敏感的(儘管有一些字元集從來不是忽略大小寫,例如捷克語)。這意味著,如果你用col_name LIKE ’a%’搜尋,你將得到所有以A或a開始的列值。如果你想要使這個搜尋大小寫敏感,使用象INDEX(col_name, "A")=0檢查一個首碼。或如果列值必須確切是"A",使用STRCMP(col_name, "A") = 0。
簡單的比較操作(>=、>、= 、< 、<=、排序和彙總)是基於每個字元的“排序值”。有同樣排序值的字元(象E,e和’e)被視為相同的字元!
LIKE比較在每個字元的大寫值上進行(E==e 但是E<>’e)。
如果你想要一個列總是被當作大小寫敏感的方式,聲明它為BINARY。見7.7 CREATE TABLE句法。
如果你使用以所謂的big5編碼的中文資料,你要使所有的字元列是BINARY,它可行,是因為big5編碼字元的排序次序基於 ASCII代碼的順序。
NULL值的概念是造成SQL的新手的混淆的普遍原因,他們經常認為NULL是和一個Null 字元串’’的一樣的東西。不是這樣的!例如,下列語句是完全不同的:
mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");
兩個語句把值插入到phone列,但是第一個插入一個NULL值而第二個插入一個Null 字元串。第一個的含義可以認為是“電話號碼不知道”,而第二個則可意味著“她沒有電話”。在SQL中,NULL值在於任何其他值甚至NULL值比較時總是假的(FALSE)。包含NULL的一個運算式總是產生一個NULL值,除非在包含在運算式中的運算子和函數的文檔中指出。在下列例子,所有的列返回NULL:
mysql> SELECT NULL,1+NULL,CONCAT(’Invisible’,NULL);
如果你想要尋找值是NULL的列,你不能使用=NULL測試。下列語句不返回任何行,因為對任何錶達式,expr = NULL是假的:
mysql> SELECT * FROM my_table WHERE phone = NULL;
要想尋找NULL值,你必須使用IS NULL測試。下例顯示如何找出NULL電話號碼和空的電話號碼:
mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";
在 MySQL中,就像很多其他的SQL伺服器一樣,你不能索引可以有NULL值的列。你必須聲明這樣的列為NOT NULL,而且,你不能插入NULL到索引的列中。當用LOAD DATA INFILE讀取資料時,空列用’’更新。如果你想要在一個列中有NULL值,你應該在文字檔中使用\N。字面詞’NULL’也可以在某些情形下使用。 見7.16 LOAD DATA INFILE句法。當使用ORDER BY時,首先呈現NULL值。如果你用DESC以降序排序,NULL值最後顯示。當使用GROUP BY時,所有的NULL值被認為是相等的。為了有助於NULL的處理,你能使用IS NULL和IS NOT NULL運算子和IFNULL()函數。
對某些列類型,NULL值被特殊地處理。如果你將NULL插入表的第一個TIMESTAMP列,則插入當前的日期和時間。如果你將NULL插入一個AUTO_INCREMENT列,則插入順序中的下一個數字。
你可以在GROUP BY、ORDER BY或在HAVING部分中使用別名引用列。別名也可以用來為列取一個更好點的名字:
SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;
注 意,你的 ANSI SQL 不允許你在一個WHERE子句中引用一個別名。這是因為在WHERE代碼被執行時,列值還可能沒有終結。例如下列查詢是不合法:SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
WHERE語句被執行以確定哪些行應該包括GROUP BY部分中,而HAVING用來決定應該只用結果集合中的哪些行。
因為MySQL不支援子選擇或在DELETE語句中使用多個表,你應該使用下列方法從2個關聯的表中刪除行:
在主表中基於某個WHERE條件SELECT行。
在主表中基於相同的條件DELETE行。
DELETE FROM related_table WHERE related_column IN (selected_rows)
如 果在related_column查詢中的字元的全部數量超過1,048,576(預設值max_allowed_packet),你應該分成更小的部分 並且執行多個DELETE語句。如果related_column是一個索引,你每次只刪除100-1000個related_column id將可能使得DELETE最快。如果related_column不是一個索引,速度與IN子句中參數的數量無關。
如果你有一個複雜的查詢,涉及多個表,但沒有返回任何行,你應該使用下列過程尋找你的詢問有什麼不對:
EXPLAIN測試查詢並且檢查你是否能找出顯然是錯誤的一些東西。見7.22 EXPLAIN句法(得到關於一個SELECT的資訊)。
僅選擇那些在WHERE子句中使用的欄位。一次從查詢中刪除一個表,直到它返回一些行。如果表很大,對查詢使用LIMIT 10是一個好主意。
對應該已經匹配一行的列做一個SELECT,針對從詢問中做後被刪除的表。如果你將FLOAT或DOUBLE列與有小數的數字進行比較,你不能使用=!。這個問題在大多數電腦語言是常見的,因為浮點值不是準確的值。
mysql> SELECT * FROM table_name WHERE float_column=3.5;
->
mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
在大多數情況下,將FLOAT改成一個DOUBLE將修正它!
如 果你仍然不能發現錯誤是什麼,建立一個最小的可運行mysql test < query.sql的測試來顯示你的問題。你可以用mysqldump --quick database tables > query.sql建立一個測試檔案,在一個編輯器編輯檔案,刪除一些插入行(如果有太多這些語句)並且在檔案末尾加入你的選擇語句。測試你仍然有問題, 可以這樣做:
shell> mysqladmin create test2
shell> mysql test2 < query.sql
使用mysqlbug的郵寄測試檔案到mysql@lists.mysql.com。
如果ALTER TABLE死於這樣一個錯誤:
Error on rename of ’./database/name.frm’ to ’./database/B-a.frm’ (Errcode: 17)
問題可能是MySQL在前一個ALTER TABLE中已經崩潰並且留下了一個名為“A-xxx”或“B-xxx”的老的資料庫表。在這種情況下,到MySQL資料目錄中並刪除所有名字以A-或B-開始的檔案。(你可以把他們移到別的地方而不是刪除他們)。ALTER TABLE工作方式是:以要求的改變建立一個名為“A-xxx”的新表。
從老表把所有行拷貝到“A-xxx”。
老表被改名為“B-xxx”。
“A-xxx”被改名為你的老表的名字。
“B-xxx”被刪除。
如果某些改名操作出錯,MySQL試圖還原改變。如果出錯嚴重(當然,這不應該發生。),MySQL可能留下了老表為“B-xxx”但是一個簡單改名就應該恢複你的資料。
SQL的要點是中抽象應用程式以避免資料存放區格式。你應該總是以你想要檢索資料的意願指定順序。例如:
SELECT col_name1, col_name2, col_name3 FROM tbl_name;
將以col_name1、col_name2、col_name3的順序返回列,而:
SELECT col_name1, col_name3, col_name2 FROM tbl_name;
將以col_name1、col_name3、col_name2的順序返回列。
在一個應用程式中,你應該決不基於他們的位置使用SELECT * 檢索列,因為被返回的列的順序永遠不能保證;對你的資料庫的一個簡單改變可能導致你的應用程式相當有戲劇性地失敗。
不管怎樣,如果你想要改變列的順序,你可以這樣做:
以正確的列順序建立一張新表。
執行INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
刪除或改名old_table。
ALTER TABLE new_table RENAME old_table。
#取消檔案系統的外部鎖
skip-locking#不進行網域名稱反解析,注意由此帶來的許可權/授權問題
skip-name-resolve#索引緩衝,根據記憶體大小而定,如果是獨立的db伺服器,可以設定高達80%的記憶體總量
key_buffer = 512M
#串連排隊列表總數
back_log = 200
max_allowed_packet = 2M
#開啟表緩衝總數,可以避免頻繁的開啟資料表產生的開銷
table_cache = 512
#每個線程排序所需的緩衝
sort_buffer_size = 4M
#每個線程讀取索引所需的緩衝
read_buffer_size = 4M
#MyISAM表發生變化時重新排序所需的緩衝
myisam_sort_buffer_size = 64M
#緩衝可重用的線程數
thread_cache = 128
#查詢結果緩衝
query_cache_size = 128M
#設定逾時時間,能避免長串連
set-variable = wait_timeout=60
#最大並發線程數,cpu數量*2
thread_concurrency = 4
#記錄慢查詢,然後對慢查詢一一最佳化
log-slow-queries = slow.log
long_query_time = 1
#關閉不需要的表類型,如果你需要,就不要加上這個
skip-innodb
skip-bdb