<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    seaairland

     

    MySQL常見錯誤問答

    18.2.1 MySQL server has gone away錯誤

    本小節(jié)也涉及有關(guān)Lost connection to server during query的錯誤。

    MySQL server has gone away錯誤最常見的原因是服務(wù)器超時了并且關(guān)閉了連接。缺省地,如果沒有事情發(fā)生,服務(wù)器在 8個小時后關(guān)閉連接。你可在啟動mysqld時通過設(shè)置wait_timeout變量改變時間限制。

    你可以通過執(zhí)行mysqladmin version并且檢驗正常運行的時間來檢查MySQL還沒死掉。

    如果你有一個腳本,你只須再發(fā)出查詢讓客護進行一次自動的重新連接。

    在這種請下,你通常能獲得下列錯誤代碼(你得到的是OS相關(guān)的):

    CR_SERVER_GONE_ERROR 客戶不能發(fā)送一個問題給服務(wù)器。
    CR_SERVER_LOST 當(dāng)寫服務(wù)器時,客戶沒有出錯,但是它沒有得到對問題的一個完整的答案(或任何答案)。

    如果你向服務(wù)器發(fā)送不正確的或太大的查詢,你也可能得到這些錯誤。如果mysqld得到一個太大或不正常的包,它認為客戶出錯了并關(guān)閉連接。如果你需要較大的查詢(例如,如果你正在處理較大的BLOB列),你可以使用-O max_allowed_packet=#選項(缺省1M)啟動mysqld以增加查詢限制。多余的內(nèi)存按需分配,這樣mysqld只有在你發(fā)出較大差詢時或mysqld必須返回較大的結(jié)果行時,才使用更多的內(nèi)存!

    18.2.2 Can't connect to [local] MySQL server錯誤

    一個MySQL客戶可以兩種不同的方式連接mysqld服務(wù)器:Unix套接字,它通過在文件系統(tǒng)中的一個文件(缺省“/tmp/mysqld.sock”)進行連接;或TCP/IP,它通過一個端口號連接。Unix套接字比TCP/IP更快,但是只有用在連接同一臺計算機上的服務(wù)器。如果你不指定主機名或如果你指定特殊的主機名localhost,使用Unix套接字。

    錯誤(2002)Can't connect to ...通常意味著沒有一個MySQL服務(wù)器運行在系統(tǒng)上或當(dāng)試圖連接mysqld服務(wù)器時,你正在使用一個錯誤的套接字文件或TCP/IP端口。

    由檢查(使用ps)在你的服務(wù)器上有一個名為mysqld的進程啟動!如果沒有任何mysqld過程,你應(yīng)該啟動一個。見4.15.2 啟動MySQL服務(wù)器的問題。

    如果一個mysqld過程正在運行,你可以通過嘗試這些不同的連接來檢查服務(wù)器(當(dāng)然,端口號和套接字路徑名可能在你的安裝中是不同的):

    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命令使用反引號“`”而非正引號“'”;這些導(dǎo)致hostname輸出(即,當(dāng)前主機名)被代替進mysqladmin命令中。

    這是可能造成Can't connect to local MySQL server錯誤的一些原因:

    • mysqld 不在運行。
    • 你正在使用MIT-pthreads的一個系統(tǒng)上運行。如果正在運行在一個沒有原生線程的系統(tǒng)上,mysqld使用 MIT-pthreads 軟件包。見4.2 由MySQL支持的操作系統(tǒng)。然而,MIT-pthreads不支持Unix套接字,因此當(dāng)與服務(wù)器連接時,在這樣一個系統(tǒng)上,你總是必須明確地指定主機名。試試使用這個命令檢查到服務(wù)器的連接:
      shell> mysqladmin -h `hostname` version
      
    • 某人刪除了mysqld使用的Unix套接字(缺省“/tmp/mysqld.sock”)。你可能有一個cron任務(wù)刪除了MySQL套接字(例如,一個把舊文件從“/tmp”目錄中刪除的任務(wù))。你總是可以運行mysqladmin version并且檢查mysqladmin正在試圖使用的套接字確實存在。在這種情況下,修復(fù)方法是刪除cron任務(wù)而不刪除“mysqld.sock 或?qū)⑻捉幼址旁谄渌胤健D隳苡眠@個命令在MySQL配置時指定一個不同的套接字地點:
      shell> ./configure --with-unix-socket-path=/path/to/socket
      

      你也可以使用--socket=/path/to/socket選項啟動safe_mysqld和在啟動你的MySQL客戶前設(shè)置環(huán)境變量MYSQL_UNIX_PORT為套接字路徑名。你可用--socket=/path/to/socket選項啟動mysqld服務(wù)器。如果你改變了服務(wù)器的套接字路徑名,你也必須通知MySQL客戶關(guān)于新路徑的情況。你可以通過設(shè)置環(huán)境變量MYSQL_UNIX_PORT為套接字路徑名或由提供套接字路徑名作為客戶的參數(shù)做到。你可用這個命令測試套接字:

      shell> mysqladmin --socket=/path/to/socket version
      
    • 你正在使用 Linux和線程已經(jīng)死了(核心傾倒了)。在這種情況中,你必須殺死其它mysqld線程(例如在啟動一個新的MySQL服務(wù)器之前,可以用mysql_zap腳本)。見18.1 如果MySQL總是崩潰怎么辦。

    如果你得到錯誤Can't connect to MySQL server on some_hostname,你可以嘗試下列步驟找出問題是什么:

    • 通過執(zhí)行telnet your-host-name tcp-ip-port-number并且按幾次回車來檢查服務(wù)器是否正常運行。如果有一個MySQL運行在這個端口上,你應(yīng)該得到一個包含正在運行的MySQL服務(wù)器的版本號的應(yīng)答。如果你得到類似于telnet: Unable to connect to remote host: Connection refused的一個錯誤,那么沒有服務(wù)器在使用的端口上運行。
    • 嘗試連接本地機器上的mysqld守護進程,并用mysqladmin variables檢查mysqld被配置使用的TCP/IP端口(變量port)。
    • 檢查你的mysqld服務(wù)器沒有用--skip-networking選項啟動。

    18.2.3 Host '...' is blocked錯誤

    如果你得到象這樣的一個錯誤:

    Host 'hostname' is blocked because of many connection errors.
    Unblock with 'mysqladmin flush-hosts'
    

    這意味著,mysqld已經(jīng)得到了大量(max_connect_errors)的主機'hostname'的在中途被中斷了的連接請求。在max_connect_errors次失敗請求后,mysqld認定出錯了(象來字一個黑客的攻擊),并且阻止該站點進一步的連接,直到某人執(zhí)行命令mysqladmin flush-hosts

    缺省地,mysqld在10個連接錯誤后阻塞一臺主機。你可以通過象這樣啟動服務(wù)器很容易地調(diào)整它:

    shell> safe_mysqld -O max_connect_errors=10000 &
    

    注意,對給定的主機,如果得到這條錯誤消息,你應(yīng)該首先檢查該主機的TCP/IP連接有沒有問題。如果你的TCP/IP連接不在運行,增加max_connect_errors變量的值對你也不會有幫助!

    18.2.4 Too many connections錯誤

    如果在你試土連接MySQL時,你得到錯誤Too many connections,這意味著已經(jīng)有max_connections個客戶連接了mysqld服務(wù)器。

    如果你需要比缺省(100)更多的連接,那么你應(yīng)該重啟mysqld,用更大的 max_connections 變量值。

    注意,mysqld實際上允許(max_connections+1)個客戶連接。最后一個連接是為一個用Process權(quán)限的用戶保留的。通過不把這個權(quán)限給一般用戶(他們不應(yīng)該需要它),有這個權(quán)限一個管理員可以登錄并且使用SHOW PROCESSLIST找出什么可能出錯。見7.21 SHOW句法(得到表,列的信息)。

    18.2.5 Out of memory錯誤

    如果你發(fā)出查詢并且得到類似于下面的錯誤:

    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。這個錯誤的原因很簡單,客戶沒有足夠的內(nèi)存存儲全部結(jié)果。

    為了修正這個問題,首先檢查你的查詢是否正確。它應(yīng)該返回這么多的行,這合理嗎?如果是這樣,你可以使用mysql --quick,它使用mysql_use_result()檢索結(jié)果集合。這將較少的負擔(dān)放在了客戶端(只是服務(wù)器更多)。

    18.2.6 Packet too large錯誤

    當(dāng)一個MySQL客戶或mysqld服務(wù)器得到一個比max_allowed_packet個字節(jié)長的包,它發(fā)出一個Packet too large錯誤并終止連接。

    如果你正在使用mysql客戶,你可以通過用mysql --set-variable=max_allowed_packet=8M指定一個更大的緩沖區(qū)來啟動客戶程序。

    如果你正在使用不允許你指定最大包大小的其他客戶(例如 DBI),你需要在你啟動服務(wù)器時設(shè)置包大小。你可以使用mysqld的命令行選項設(shè)置max_allowed_packet為一個更大的尺寸。例如,如果你正期望將一個全長的BLOB存入一張表中,你將需要用--set-variable=max_allowed_packet=24M選項來啟動服務(wù)器。

     

    18.2.7 The table is full錯誤

    這個錯誤發(fā)生在內(nèi)存臨時表變得比tmp_table_size字節(jié)大時。為了避免這個問題,你可以使用mysqld-O tmp_table_size=#選項來增加臨時表的大小,或在你發(fā)出有疑問的查詢之前使用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,你正在以錯誤的次序調(diào)用客戶函數(shù)!

    這可能發(fā)生,例如,如果你正在使用mysql_use_result()并且在你已經(jīng)調(diào)用了mysql_free_result()之前試圖執(zhí)行新查詢。如果你在mysql_use_result()mysql_store_result()之間試圖執(zhí)行返回數(shù)據(jù)的2個查詢,它也可能發(fā)生。

    18.2.9 Ignoring user錯誤

    如果你得到下列錯誤:

    Found wrong password for user: 'some_user@some_host'; Ignoring user

    這意味著在mysqld啟動時或在它再次裝載權(quán)限表時,它在user表中找到了一個有一個無效口令的條目。結(jié)果,條目簡單地被權(quán)限系統(tǒng)忽略。

    可能導(dǎo)致這個問題的原因和修正:

    • 你可能正在運行一個有一個老的user表的新版本mysqld。你可以通過執(zhí)行mysqlshow mysql user看看口令字段是否少于 16個字符來檢查它。如果是這樣,你可以通過運行scripts/add_long_password腳本改正這種情況。
    • 用戶有一個老式的口令(8個字符長)并且你沒使用--old-protocol選項啟動mysqld。用一個新口令更新在user表中的用戶或用--old-protocol重啟mysqld
    • 你沒有使用PASSWORD()函數(shù)在在user表中指定了一個口令。使用mysql以一個新口令更新在user表中的用戶。確保使用PASSWORD()函數(shù):
      mysql> update user set password=PASSWORD('your password')
                 where user='XXX';
      

    18.2.10 Table 'xxx' doesn't exist錯誤

    如果你得到錯誤Table 'xxx' doesn't existCan't find file: 'xxx' (errno: 2),這意味著在當(dāng)前數(shù)據(jù)庫中沒有名為xxx的表存在。

    注意,因為MySQL使用目錄和文件存儲數(shù)據(jù)庫和表,數(shù)據(jù)庫和表名件是區(qū)分大小寫的!(在Win32上,數(shù)據(jù)庫和表名不是區(qū)分大小寫的,但是在查詢中對所有表的引用必須使用相同的大小寫!)

    你可以用SHOW TABLES檢查你在當(dāng)前數(shù)據(jù)庫中有哪個表。見7.21 SHOW句法(得到表、列的信息)。

    18.3 MySQL怎樣處理一個溢出的磁盤

    當(dāng)出現(xiàn)一個磁盤溢出的情況時,MySQL做下列事情:

    • 它每分鐘檢查一次看是否有足夠空間寫入當(dāng)前行。如果有足夠的空間,它繼續(xù)好像發(fā)生什么事情。
    • 每6分鐘它將有關(guān)磁盤溢出的警告寫入日志文件。

    為了緩和這個問題,你可以采取下列行動:

    • 繼續(xù),你只需釋放足夠的空閑磁盤空間以便插入所有記錄。
    • 放棄線程,你必須發(fā)一個mysqladmin kill到線程。在下一次檢查磁盤時,線程將被放棄(在1分鐘內(nèi))。
    • 注意,其他線程可能正在等待引起“磁盤溢出”條件的表。如果你有幾個“鎖定的”的線程,殺死正在等待磁盤溢出條件的那個線程將允許其他線程繼續(xù)。

    18.4 如何從一個文本文件運行SQL命令

    一般地,mysql客戶被交互性地使用,象這樣:

    shell> mysql database

    然而,也可以把你的SQL命令放在一個文件中并且告訴mysql從該文件讀取其輸入。要想這樣做,創(chuàng)造一個文本文件“text_file”,它包含你想要執(zhí)行的命令。然后如下那樣調(diào)用mysql

    shell> mysql database < text_file
    

    你也能啟動有一個USE db_name語句的文本文件。在這種情況下,在命令行上指定數(shù)據(jù)庫名是不必要的:

    shell> mysql < text_file
    
    見12.1 不同的MySQL程序概述。 

    18.5 MySQL在哪兒存儲臨時文件

    MySQL使用TMPDIR環(huán)境變量的值作為存儲臨時文件的目錄的路徑名。如果你沒有設(shè)置TMPDIRMySQL使用系統(tǒng)缺省值,它通常是“/tmp”“/usr/tmp”。如果包含你的臨時文件目錄的文件系統(tǒng)太小,你應(yīng)該編輯safe_mysqld設(shè)定TMPDIR指向你有足夠空間的一個文件系統(tǒng)!你也可以使用mysqld的--tmpdir選項目設(shè)置臨時目錄。

    MySQL以“隱含文件”創(chuàng)建所有臨時文件。這保證了如果mysqld被終止,臨時文件也將被刪除。使用隱含文件的缺點是你將看不到一個大的臨時文件填滿了臨時文件目錄所在的文件系統(tǒng)。

    當(dāng)排序(ORDER BYGROUP BY)時,MySQL通常使用一個或兩個臨時文件。最大磁盤空間需求是:

    (存儲東西的長度 + sizeof (數(shù)據(jù)庫指針))
    * 匹配的行數(shù)
    * 2
    

    sizeof(數(shù)據(jù)庫指針) 通常是4,但是在未來對確實很大的表可能增加。

    對一些SELECT查詢,MySQL也創(chuàng)建臨時SQL表。這些沒被隱含且有“SQL_*”格式的名字。

    ALTER TABLE OPTIMIZE TABLE在原數(shù)據(jù)庫表的同一個目錄中創(chuàng)建一張臨時表。

    18.6 怎樣保護“/tmp/mysql.sock ”不被刪除

    如果你有這個問題,事實上任何人可以刪除MySQL通訊套接字“/tmp/mysql.sock”,在Unix的大多數(shù)版本上,你能通過為其設(shè)置sticky(t)位來保護你的“/tmp”文件系統(tǒng)。作為root登錄并且做下列事情:

    shell> chmod +t /tmp
    

    這將保護你的“/tmp”文件系統(tǒng)使得文件僅能由他們的所有者或超級用戶(root)刪除。

    你能執(zhí)行ls -ld /tmp檢查sticky位是否被設(shè)置,如果最后一位許可位是t,該位被設(shè)置了。

    18.7 Access denied錯誤

    見6.6 權(quán)限系統(tǒng)如何工作。并且特別要看6.13 引起Access denied錯誤的原因。

    18.8 怎樣作為一個一般用戶運行MySQL

    MySQL服務(wù)器mysqld能被任何用戶啟動并運行。為了將mysqld改由Unix用戶user_name來運行,你必須做下列事情:

    1. 如果它正在運行,停止服務(wù)器(使用mysqladmin shutdown)。
    2. 改變數(shù)據(jù)庫目錄和文件以便user_name有權(quán)限讀和寫文件(你可能需要作為Unix的root用戶才能做到):
      shell> chown -R user_name /path/to/mysql/datadir
      

      如果在MySQL數(shù)據(jù)目錄中的目錄或文件是符號鏈接,你也將需要順著那些鏈接并改變他們指向的目錄和文件。chown -R不能跟隨符號鏈接。

    3. user_name用戶啟動服務(wù)器,或如果你正在使用MySQL 3.22或以后版本,以Unix root用戶啟動mysqld并使用--user=user_name選項,mysqld將在接受任何連接之前切換到以Unix user_name用戶運行。
    4. 如果在系統(tǒng)被重新啟動時,你使用mysql.server腳本啟動mysqld,你應(yīng)該編輯mysql.serversu以用戶user_name運行mysqld,或使用--user選項調(diào)用mysqld。(不改變safe_mysqld是必要的。)

    現(xiàn)在,你的mysqld進程應(yīng)該正在作為Unix用戶user_name運行,并運行完好。盡管有一件事情沒有變化:權(quán)限表的內(nèi)容。缺省 地(就在運行了腳本mysql_install_db安裝的權(quán)限表后),MySQL用戶root是唯一有存取mysql數(shù)據(jù)庫或創(chuàng)建或拋棄數(shù)據(jù)庫權(quán)限的用戶。除非你改變了那些權(quán)限,否則他們?nèi)匀槐3帧.?dāng)你作為一個Unix用戶而不是root登錄時,這不應(yīng)該阻止你作為MySQLroot用戶來存取MySQL;只要為客戶程序指定-u root的選項。

    注意通過在命令行上提供-u root,作為root存取MySQL,與作為Unix root用戶或其他Unix用戶運行MySQL沒有關(guān)系MySQL的存取權(quán)限和用戶名與Unix用戶名字是完全分開的。唯一與Unix用戶名有關(guān)的是,如果當(dāng)你調(diào)用一個客戶程序時,你不提供一個-u選項,客戶將試圖使用你的Unix登錄名作為你的MySQL用戶名進行連接。

    如果你的Unix機器本身不安全,你可能應(yīng)該至少在存取表中為MySQLroot用戶放上一個口令。否則,在那臺機器上有一個帳號的任何用戶能運行mysql -u root db_name并且做他喜歡做的任何事情。

    18.9 怎樣重新設(shè)置一個忘記的口令

    如果你忘記了MySQLroot用戶的口令,你可以用下列過程恢復(fù)它。

    1. 通過發(fā)送一個kill(不是kill -9)到mysqld服務(wù)器來關(guān)閉mysqld服務(wù)器。pid 被保存在一個.pid文件中,通常在MySQL數(shù)據(jù)庫目錄中:
      kill `cat /mysql-data-directory/hostname.pid`
      

      你必須是一個UNIX root用戶或運行服務(wù)器的相同用戶做這個。

    2. 使用--skip-grant-tables選項重啟mysqld
    3. mysql -h hostname mysql連接mysqld服務(wù)器并且用一條GRANT命令改變口令。見7.26 GRANTREVOKE句法。你也可以用mysqladmin -h hostname -u user password 'new password' 進行。
    4. mysqladmin -h hostname flush-privileges或用SQL命令FLUSH PRIVILEGES來裝載權(quán)限表。

    18.10 文件許可權(quán)限問題

    如果你有與文件許可有關(guān)的問題,例如,如果當(dāng)你創(chuàng)建一張表時,mysql發(fā)出下列錯誤消息:

    ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13) 
    

    那么可能是在mysqld啟動時,環(huán)境變量UMASK可能設(shè)置不正確。缺省的umask值是0660。你可以如下啟動safe_mysqld改變其行為:

    shell> UMASK=384  # = 600 in octal
    shell> export UMASK
    shell> /path/to/safe_mysqld &
    

    18.11 文件沒找到

    如果你從MySQL得到ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24)或任何其他有errno 23errno 24的錯誤,它意味著,你沒有為MySQL分配足夠的文件描述符。你能使用perror實用程序得到錯誤號含義是什么的描述:

    shell> perror 23
    File table overflow
    shell> perror 24
    Too many open files
    

    這里的問題是mysqld正在試圖同時保持打開太多的文件。你也可以告訴mysqld一次不打開那么多的文件,或增加mysqld可得到的文件描述符數(shù)量。

    為了告訴mysqld一次保持打開更少的文件,你可以通過使用safe_mysqld-O table_cache=32選項(缺省值是64)使表緩沖更小。減小max_connections值也將減少打開文件的數(shù)量(缺省值是90)。

    要想改變mysqld可用的文件描述符數(shù)量,修改safe_mysqld腳本。腳本中有一條注釋了的行ulimit -n 256。你可以刪除'#'字符來去掉該行的注釋,并且改變數(shù)字256改變?yōu)?code>mysqld可用的文件描述符的數(shù)量。

    ulimit 能增加文件描述符的數(shù)量,但是只能到操作系統(tǒng)強加的限制。如果你需要增加每個進程可用的文件描述符數(shù)量的OS限制,參見你的操作系統(tǒng)文檔。

    注意,如果你運行tcsh外殼,ulimit將不工作!當(dāng)你請求當(dāng)前限制時,tcsh也將報告不正確的值!在這種情況下,你應(yīng)該用sh啟動safe_mysqld

    18.12 使用DATE列的問題

    一個DATE值的格式是'YYYY-MM-DD'。根據(jù)ANSI SQL,不允許其他格式。你應(yīng)該在UPDATE表達式和SELECT語句的WHERE子句中使用這個格式。例如:

    mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';
    

    為了方便,如果日期用在數(shù)字上下文,MySQL自動變換一個日期到一個數(shù)字(并且反過來也如此)。當(dāng)更新時和將一個日期與TIMESTAMPDATEDATETIME列比較的一個WHERE子句中,也是足夠靈活以允許一種“寬松”的字符串格式。(寬松格式意味著任何標點字符用作在部件之間的分割符。例如,'1998-08-15''1998#08#15'是等價的。)MySQL也能變換不包含分割符的一個字符串(例如 '19980815'),如果它作為一個日期說得通。

    特殊日期'0000-00-00'可以作為'0000-00-00'被存儲和檢索當(dāng)通過MyODBC使用一個'0000-00-00'日期時,在MyODBC 2.50.12和以上版本,它將自動被轉(zhuǎn)換為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() 是字符串函數(shù),因此它將idate轉(zhuǎn)換為一個字符串并且實施字符串比較。它不將'19970505'轉(zhuǎn)換為一個日期并實施日期比較。

    注意,MySQL不檢查日期是否正確。如果你存儲一個不正確的日期,例如'1998-2-31',錯誤的日期將被存儲。如果日期不能被變換到任何合理的值,在DATE字段中存儲一個0。這主要是一個速度問題并且我們認為檢查日期是應(yīng)用程序的責(zé)任,而不服務(wù)器。

    18.13 時區(qū)問題

    如果你有一個問題,SELECT NOW()以GMT時間返回值而不是你的本地時間,你必須設(shè)定TZ環(huán)境變量為你的當(dāng)前時區(qū)。這應(yīng)該在服務(wù)器運行的環(huán)境進行,例如在safe_mysqldmysql.server中。

    18.14 在搜索中的大小寫敏感性

    缺省地,MySQL搜索是大小寫不敏感的(盡管有一些字符集從來不是忽略大小寫的,例如捷克語)。這意味著,如果你用col_name LIKE 'a%'搜尋,你將得到所有以Aa開始的列值。如果你想要使這個搜索大小寫敏感,使用象INDEX(col_name, "A")=0檢查一個前綴。或如果列值必須確切是"A",使用STRCMP(col_name, "A") = 0

    簡單的比較操作(>=、>、= 、< 、<=、排序和聚合)是基于每個字符的“排序值”。有同樣排序值的字符(象E,e和'e)被視為相同的字符!

    LIKE 比較在每個字符的大寫值上進行(E==e 但是E<>'e)。

    如果你想要一個列總是被當(dāng)作大小寫敏感的方式,聲明它為BINARY。見7.7 CREATE TABLE句法。

    如果你使用以所謂的big5編碼的中文數(shù)據(jù),你要使所有的字符列是BINARY,它可行,是因為big5編碼字符的排序順序基于 ASCII代碼的順序。

    18.15 NULL值問題

    NULL 值的概念是造成SQL的新手的混淆的普遍原因,他們經(jīng)常認為NULL是和一個空字符串''的一樣的東西。不是這樣的!例如,下列語句是完全不同的:

    mysql> INSERT INTO my_table (phone) VALUES (NULL);
    mysql> INSERT INTO my_table (phone) VALUES ("");
    

    兩個語句把值插入到phone列,但是第一個插入一個NULL值而第二個插入一個空字符串。第一個的含義可以認為是“電話號碼不知道”,而第二個則可意味著“她沒有電話”。

    在SQL中,NULL值在于任何其他值甚至NULL值比較時總是假的(FALSE)。包含NULL的一個表達式總是產(chǎn)生一個NULL值,除非在包含在表達式中的運算符和函數(shù)的文檔中指出。在下列例子,所有的列返回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服務(wù)器一樣,你不能索引可以有NULL值的列。你必須聲明這樣的列為NOT NULL,而且,你不能插入NULL到索引的列中。

    當(dāng)用LOAD DATA INFILE讀取數(shù)據(jù)時,空列用''更新。如果你想要在一個列中有NULL值,你應(yīng)該在文本文件中使用\N。字面上的詞'NULL'也可以在某些情形下使用。見7.16 LOAD DATA INFILE句法。

    當(dāng)使用ORDER BY時,首先呈現(xiàn)NULL值。如果你用DESC以降序排序,NULL值最后顯示。當(dāng)使用GROUP BY時,所有的NULL值被認為是相等的。

    為了有助于NULL的處理,你能使用IS NULLIS NOT NULL運算符和IFNULL()函數(shù)。

    對某些列類型,NULL值被特殊地處理。如果你將NULL插入表的第一個TIMESTAMP列,則插入當(dāng)前的日期和時間。如果你將NULL插入一個AUTO_INCREMENT列,則插入順序中的下一個數(shù)字。

     

    18.16 alias問題

    你可以在GROUP BYORDER 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代碼被執(zhí)行時,列值還可能沒有終結(jié)。例如下列查詢是不合法

    SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
    

    WHERE 語句被執(zhí)行以確定哪些行應(yīng)該包括GROUP BY部分中,而HAVING用來決定應(yīng)該只用結(jié)果集合中的哪些行。

    18.17 從關(guān)聯(lián)的表中刪除行

    因為MySQL不支持子選擇或在DELETE語句中使用多個表,你應(yīng)該使用下列方法從2個關(guān)聯(lián)的表中刪除行:

    1. 在主表中基于某個WHERE條件SELECT行。
    2. 在主表中基于相同的條件DELETE行。
    3. DELETE FROM related_table WHERE related_column IN (selected_rows)

    如果在related_column查詢中的字符的全部數(shù)量超過1,048,576(缺省值max_allowed_packet),你應(yīng)該分成更小的部分并且執(zhí)行多個DELETE語句。如果related_column是一個索引,你每次只刪除100-1000個related_column id將可能使得DELETE最快。如果related_column不是一個索引,速度與IN子句中參數(shù)的數(shù)量無關(guān)。

    18.18 解決沒有匹配行的問題

    如果你有一個復(fù)雜的查詢,涉及多個表,但沒有返回任何行,你應(yīng)該使用下列過程查找你的詢問有什么不對:

    1. EXPLAIN 測試查詢并且檢查你是否能找出顯然是錯誤的一些東西。見7.22 EXPLAIN句法(得到關(guān)于一個SELECT的信息)。
    2. 僅選擇那些在WHERE子句中使用的字段。
    3. 一次從查詢中刪除一個表,直到它返回一些行。如果表很大,對查詢使用LIMIT 10是一個好主意。
    4. 對應(yīng)該已經(jīng)匹配一行的列做一個SELECT,針對從詢問中做后被刪除的表。
    5. 如果你將FLOATDOUBLE列與有小數(shù)的數(shù)字進行比較,你不能使用=!。這個問題在大多數(shù)計算機語言是常見的,因為浮點值不是準確的值。
      mysql> SELECT * FROM table_name WHERE float_column=3.5;
         ->
      mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
      

      在大多數(shù)情況下,將FLOAT改成一個DOUBLE將修正它!

    6. 如果你仍然不能發(fā)現(xiàn)錯誤是什么,創(chuàng)建一個最小的可運行mysql test < query.sql的測試來顯示你的問題。你可以用mysqldump --quick database tables > query.sql創(chuàng)建一個測試文件,在一個編輯器編輯文件,刪除一些插入行(如果有太多這些語句)并且在文件末尾加入你的選擇語句。測試你仍然有問題,可以這樣做:
      shell> mysqladmin create test2
      shell> mysql test2 < query.sql
      

      使用mysqlbug的郵寄測試文件到mysql@lists.mysql.com。

    18.19 與ALTER TABLE有關(guān)的問題

    如果ALTER TABLE死于這樣一個錯誤:

    Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)
    

    問題可能是MySQL在前一個ALTER TABLE中已經(jīng)崩潰并且留下了一個名為“A-xxx”“B-xxx”的老的數(shù)據(jù)庫表。在這種情況下,到MySQL數(shù)據(jù)目錄中并刪除所有名字以A-B-開始的文件。(你可以把他們移到別的地方而不是刪除他們)。

    ALTER TABLE 工作方式是:

    • 以要求的改變創(chuàng)建一個名為“A-xxx”的新表。
    • 從老表把所有行拷貝到“A-xxx”
    • 老表被改名為“B-xxx”
    • “A-xxx” 被改名為你的老表的名字。
    • “B-xxx” 被刪除。

    如果某些改名操作出錯,MySQL試圖還原改變。如果出錯嚴重(當(dāng)然,這不應(yīng)該發(fā)生。),MySQL可能留下了老表為“B-xxx”但是一個簡單改名就應(yīng)該恢復(fù)你的數(shù)據(jù)。

    18.20 怎樣改變一張表中列的順序

    SQL的要點是中抽象應(yīng)用程序以避免數(shù)據(jù)存儲格式。你應(yīng)該總是以你想要檢索數(shù)據(jù)的意愿指定順序。例如:

    SELECT col_name1, col_name2, col_name3 FROM tbl_name;
    

    將以col_name1col_name2col_name3的順序返回列,而:

    SELECT col_name1, col_name3, col_name2 FROM tbl_name; 
    

    將以col_name1col_name3col_name2的順序返回列。

    在一個應(yīng)用程序中,你應(yīng)該決不基于他們的位置使用SELECT * 檢索列,因為被返回的列的順序永遠不能保證;對你的數(shù)據(jù)庫的一個簡單改變可能導(dǎo)致你的應(yīng)用程序相當(dāng)有戲劇性地失敗。

    不管怎樣,如果你想要改變列的順序,你可以這樣做:

    1. 以正確的列順序創(chuàng)建一張新表。
    2. 執(zhí)行INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
    3. 刪除或改名old_table
    4. ALTER TABLE new_table RENAME old_table

    posted on 2006-05-06 16:57 chenhui 閱讀(1572) 評論(0)  編輯  收藏 所屬分類: 好文收集數(shù)據(jù)庫

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    介紹 IOC

    友情鏈接

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲av午夜精品一区二区三区| 国精产品一区一区三区免费视频| 亚洲一卡二卡三卡| 亚洲欧洲免费视频| 亚洲AV无码一区东京热久久| 在线播放亚洲第一字幕| 精品亚洲一区二区三区在线播放| 亚洲欧洲一区二区三区| 中文字幕亚洲第一| 亚洲精品午夜无码电影网| 国产亚洲精aa成人网站| 亚洲另类激情综合偷自拍图| 亚洲午夜福利AV一区二区无码| 亚洲情XO亚洲色XO无码| 老汉色老汉首页a亚洲| 亚洲欧洲久久精品| 国产成人精品日本亚洲专区6| 亚洲中文字幕无码一去台湾| 亚洲综合色丁香婷婷六月图片| 亚洲国产欧美一区二区三区| 久久久久亚洲国产AV麻豆| 免费视频精品一区二区| 久久99精品免费一区二区| 成人爽a毛片免费| 2021在线永久免费视频| 在线视频免费观看高清| 国产精品冒白浆免费视频| 免费在线一级毛片| 亚洲线精品一区二区三区| 亚洲欧洲免费视频| 亚洲色偷偷偷综合网| 男女猛烈激情xx00免费视频| 国产亚洲精品免费视频播放| 久久久精品2019免费观看| 毛片免费全部免费观看| 亚洲国产精品狼友中文久久久 | 中文字幕免费视频精品一| 国产好大好硬好爽免费不卡| 国国内清清草原免费视频99| 国产免费人成视频在线观看| 久久亚洲精品中文字幕三区|