MySQL FAQ version 1.0 - 차례 - 0. 0) About This Document 0.1) Copyright 1. Connection Error 1.1) Access denied 1.2) Can't connect to local MySQL server through socket '/tmp/mysql.sock' 2. 암호를잊어버린경우 3. PHP 에서의 MySQL 과관련된 Warning 메시지해결방법 작성자 : 허정수 (wertyu@nownuri.net) 작성일 : 2001 년 5 월 23 일
0.0) About This Document 본문서는필자가저술한책 MySQL Advanced Class( 출판사 : 베스트북, ISBN : 89-8397-071-5, 출판일 : 2001 년 4 월 10 일 ) 의부록 허의원의진료실 부분에서 Section 1,7 의내용을편집한문서입니다. 필자는현재까지 (2001 년 5 월 ) MySQL 에대하여두권의책을집필하였습니다. 필자가집필한책에관심있는분은 http://www.nnr.or.kr/book/diff.php 을참고하시기바랍니다. 마음같아서는집필한책을모두인터넷상에공개하고싶지만, 출판사로부터받은원고비가있고, 또돈을주고산독자도있어서, 그렇지못하고있습니다. 먼훗날책이더이상안팔릴때쯤차례로공개하겠습니다.( 그때쯤이면제책이더이상활용될수없을지도모르겠네요 ^^) 이문서는 http://www.nnr.or.kr/ 에서구할수있습니다. 새로운버전의문서가나오면, 항상위의웹사이트에게시할테니오래된문서를보는분들은위의웹사이트를방문해보시기바랍니다. 0.1) Copyright 본문서에있는내용은어떠한형태로든저자의허락이없이편집될수없으며, 상업적인용도로사용될수없습니다. 필자가문서를처음부터공개용으로만들었으면이런문제는없으나, 책으로출판되었던문서이므로출판사및독자와의관계상본문서를절대다른용도로사용할수없음을이해바랍니다. 또한, 본문서를타사이트에게시하는경우출처를 http://www.nnr.or.kr 로밝혀주시기바랍니다. 1 Connection Error 처음으로 Connection Error 에대해서알아보겠습니다. 다음과리겠습니다. 같이두내용에대해설명드 i : Access Denied ii: Can't connect to local MySQL server through socket '/tmp/mysql.sock' 위의 i, ii 문제는 MySQL 을처음사용해본초보자들이가장많이겪는문제입니다. 이문서를통하여위의문제를해결하는방법을확실히배우도록합시다. 여기서 i 문제는 MySQL 의데몬이확실히실행되고있다는것은알수있으므로, 그나마해결하기쉽습니다. 하지만, ii 문제는 MySQL 데몬이실행중인지아닌지먼저알아야하므로, 약간더어려울수있습니다. 1.1 ) Access denied 'Access denied' 에러는 ii 의경우와달리현재 MySQL 데몬이실행중이라는것입니다. 따라서 ii 경우보다는문제를해결하기가쉽습니다. 이에러메시지는다음과같은형식으로출력됩니다. 2
[wertyu@inos ~]$ mysql -u root student ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO) 이에러메시지가의미하는것은입력한사용자에게 MySQL 을사용할권한이없다는것을의미합니다. 암호를잘못지정하였거나, 사용자명을잘못지정한경우또는해당데이터베이스나테이블에접근할수있는권한이없을때발생하는에러입니다. MySQL 을처음설치한후아무런변경도하지않는경우에는 root 사용자의암호가설정되어있지않습니다. 따라서 MySQL 을처음설치한경우에는다음과같은명령으로 MySQL 서버에연결을할수있습니다. [wertyu@inos ~]$ mysql -u root mysql 여기서주의할점은 mysql 은 -u 옵션으로사용자명을주지않는경우시스템계정사용자의이름을이용한다는것입니다. 현재필자는 wertyu 라는사용자로작업을하고있는데 -u 옵션을지정하지않는이상 MySQL 에서도 wertyu 사용자로로긴을하려고합니다. 그런데 MySQL 에는초기에 wertyu 사용자가존재하지않으므로다음과같이 Access denied 에러가발생하게됩니다. [wertyu@inos ~]$ mysql mysql ERROR 1045: Access denied for user: 'wertyu@localhost' (Using password: NO) 따라서 -u 옵션으로사용자명을지정해주어야합니다. 하지만주의해야할점은 MS Windows 에서 mysql 을사용하는경우 dos 용프로그램을실행하므로사용자계정이라는것이없고따라서 anonymous 사용자로로긴을시도하게됩니다. anonymous 사용자란 mysql 데이터베이스에서 User 필드에값이없는사용자를의미합니다. 이 anonymous 사용자는 MySQL 에테스트용으로접근을할수있는사용자이지만아무런권한이없는사용자입니다. 따라서 MS Windows 사용자는꼭 -u 옵션으로사용자명을적어주어야합니다. anonymous 로 mysql 을사용하는경우 MySQL 에접속은할수있지만, 아무런권한이없는 anonymous 사용자이기때문에데이터베이스를사용하려고 use mysql 과같은 SQL 문을실행하면다음과같이 Access denied 에러가납니다. mysql> use mysql; ERROR 1044: Access denied for user: '@localhost' to database 'mysql' 따라서처음 MySQL 을사용하는독자들은로긴은되었는데데이터베이스를사용할때 Access denied 에러가나므로헷갈려하는경우가종종발생합니다. 만약 mysql 을사용하면서다음과같은에러가발생한다면사용자에게암호가걸려있는것입니다. [wertyu@inos ~]$ mysql -uroot mysql ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO) 이경우 root 사용자는 MySQL 의사용자인데 mysql 로로긴을하려고했더니, (Using password:no) 를출력하면서연결할수없다는에러메시지를출력하였습니다. 즉, 이사용자에게는암호가있는데암호를입력하지않았으므로로긴을못한다는이야기입니다. 그런데만약 -u 로사용자를지정할때 MySQL 에없는사용자를지정하면위와같은에러가발생하게됩니다. 만약위와같은에러가발생할때는 MySQL 에있는사용자인지검사를해보고 MySQL 에있는사용자라면다음과같이암호를입력하면되고, MySQL 에없는사용자라면사용자를추가하셔야합니다. [wertyu@inos ~]$ mysql -uroot -p mysql Enter password: 3
Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 20 to server version: 3.23.32 Type 'help;' or '\h' for help. Type '\c' to clear the buffer mysql> 또한 MySQL 을처음사용하는사람들이많이실수하는것중의하나가사용자를추가할때 INSERT 나 UPDATE 등으로사용자를추가하면서 FLUSH PRIVILEGES; 를실행하지않는경우입니다. MySQL 은처음실행을할때 MySQL 의권한테이블인 mysql 데이터베이스에있는테이블의내용을메모리로읽어들입니다. 이러한이유는사용자인증검사속도를빠르게하기위해서입니다. 그런데, INSERT 나 UPDATE 등으로사용자정보를변경한경우실제테이블에내용은변경되지만메모리에있는내용은변경이되지않습니다. 따라서초보자들은 'INSERT 로사용자를추가했는데, 로긴이안된다 ' 라고많이합니다. 이렇게 INSERT 나 UPDATE 로사용자정보를변경한경우에는꼭 FLUSH PRIVILEGES 로 MySQL 에게 ' 사용자정보가변경되었으니권한테이블을다시메모리로읽어들여라 ' 라고알려주어야합니다. GRANT 문으로사용자를추가하면 FLUSH PRIVILEGES 를할필요가없기때문에실수를미연에방지할수있고, 또한각사용자에대해세세한권한을쉽게줄수있으므로사용자를추가할때는 GRANT 문을이용하시기바랍니다.(GRANT 에대해서는부록 1 참고 ) 요즘은 PHP 를많이사용하는데 PHP 에서 PHP 에서는다음과같이 mysql_connect() 함수로 MySQL 에로긴을하게됩니다. $conn = mysql_connect("localhost", "phpuser", "secret") ; 그런데만약이함수에서 Access denied 에러가발생하는경우문제를쉽게해결하는방법은직접 mysql 프로그램을이용해서다음과같이사용자명에 phpuser, 암호에 secret 를입력하여로긴이가능한지살펴보는것입니다. $ mysql -u phpuser -psecret 만약로긴이가능하다면 PHP 프로그램이잘못된것이고, 로긴을할수없다면, mysql_connect() 에서지정한사용자명과암호가잘못된것이므로올바른사용자명과암호를지정해주어야합니다. MySQL 을설치하면 mysqlaccess 라는유틸리티가기본적으로포함되어있습니다. 이프로그램을이용하여사용자의권한과암호가걸려있는지등등의정보를얻을수있습니다. 사용법은다음과같습니다. mysqlaccess [host [user [db]]] OPTIONS 만약로컬호스트의 wertyu 에게 student 라는데이터베이스에어떤권한이있는지알아보기위해서는다음과같은명령을내리면됩니다.( 단, 버그인지모르겠는데현재필자가사용하는 mysqlaccess 는시스템의 root 사용자로만실행을해야결과가나오고있습니다. 만약결과가제대로나오지않는독자는 root 사용자로 mysqlaccess 를실행시켜보세요 ) [wertyu@localhost wertyu]# mysqlaccess localhost wertyu student Could not open outputfile ~/mysqlaccess.log for debugging-info 4
mysqlaccess Version 2.06, 20 Dec 2000 By RUG-AIV, by Yves Carlier (Yves.Carlier@rug.ac.be) Changes by Steve Harvey (sgh@vex.net) This software comes with ABSOLUTELY NO WARRANTY. Access-rights for USER 'wertyu', from HOST 'localhost', to DB 'student' +-----------------+---+ +-----------------+---+ Select_priv Y Shutdown_priv N Insert_priv Y Process_priv N Update_priv Y File_priv N Delete_priv Y Grant_priv N Create_priv Y References_priv Y Drop_priv Y Index_priv Y Reload_priv N Alter_priv Y +-----------------+---+ +-----------------+---+ NOTE: A password is required for user `wertyu' :-( The following rules are used: db : 'localhost','student','wertyu','y','y','y','y','y','y','n','y','y','y' host : 'Not processed: host-field is not empty in db-table.' user : 'localhost','wertyu','4e2eb14c2c15d95e','n','n','n','n','n','n','n','n','n','n','n','n','n','n' BUGs can be reported by email to Yves.Carlier@rug.ac.be 결과를보면처음 'Access-rights' 부분에서 localhost 의 wertyu 사용자에게 student 데이터베이스에대한권한들이출력됩니다. 현재 localhost 의 wertyu 사용자는 student 데이터베이스만사용할수있다는것을보여줍니다. 또한 NOTE 부분에서는 wertyu 사용자는로긴을하기위하여암호가필요하다는것을보여주고있습니다. 마지막으로 'The following rules are used' 에서는 db 테이블과 host 테이블, user 테이블에서 User 필드가 wertyu 인레코드들을출력하게됩니다. 앞의결과로서 localhost 의 wertyu 사용자는암호가있어야하고 student 데이터베이스에만접근할수있다는것을보았습니다. 그러면실제로 mysql 을사용해서로긴을해볼까요? [wertyu@inos ~]$ mysql -u wertyu -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 33 to server version: 3.23.32 Type 'help;' or '\h' for help. Type '\c' to clear the buffer mysql> use student; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> use mysql ERROR 1044: Access denied for user: 'wertyu@localhost' to database 'mysql' 처음로긴은성공으로하였고 use student 로 student 데이터베이스를사용하고자할때도성공을하였으나 use mysql 로 mysql 데이터베이스를사용하려고하니 Access denied 에러가발생하였습니다. 즉, 정리를하자면 Access denied 에러는사용자명을잘못지정하였거나암호를잘못지정하 5
였거나데이터베이스에접근할권한이없을때발생하는것입니다. 1.2 Can't connect to local MySQL server through socket '/tmp/mysql.sock' 이문제도 i) 문제와함께 MySQL 에서가장많이발생하는에러중의하나입니다. i) 문제는그래도 MySQL 데몬이실행중이기때문에에러가발생할수있는원인이많지가않아문제를해결하기쉽지만이에러는 MySQL 의데몬이실행중이지않을수도있기때문에쉽게해결할수없습니다. 하지만필자가다음에서제시하는방법을사용하면초보자라도쉽게문제를해결할수있을것입니다. ii) 에러가발생하는원인은크게다음과같습니다. i) MySQL 데몬이실행되지않았다. i) MySQL 데몬에서생성한 mysql.sock 파일과 mysql 등의클라이언트프로그램에서지정한 mysql.sock 파일의위치가서로다르다 i) MySQL 데몬은실행중이나 mysql.sock 파일이지워졌다. 먼저정확한문제해결을위해 mysql.sock 파일이무엇인지알아보겠습니다. MySQL 과클라이언트프로그램이서로연결하는데사용하는 mysql.sock 파일은유닉스소켓파일이라는파일입니다.( 파일의이름은 MySQL 을실행할때바꿔줄수있는데기본값은 mysql.sock 파일이니이책에서도 mysql.sock 파일이라는용어를계속해서사용하겠습니다.) mysql.sock 파일은 MySQL 서버와클라이언트간에서로통신을하는데사용됩니다. MySQL 과클라이언트프로그램 (mysql, 혹은 PHP 등의언어도모두클라이언트입니다 ) 이통신하는방법에는유닉스소켓파일과 TCP/IP 를이용하는방법이있습니다. 그런데유닉스소켓을사용하는것이 TCP/IP 를사용하는것보다속도가빠릅니다. 유닉스소켓은속도가빠르지만유닉스소켓은 Local System 에있는프로그램사이에만서로연결을할수있습니다. 즉서버와클라이언트모두한시스템안에있는경우에만유닉스소켓을사용할수있습니다. (MS Windows 에서는유닉스소켓을지원하지않으므로 TCP/IP 만을사용하고이런문제가발생하지않습니다.) 이렇게되면로컬에서 MySQL 서버와클라이언트는서로연결할수있는방법이유닉스소켓인 mysql.sock 파일과 TCP/IP 를이용한방법, 이렇게두가지방법이있는데 MySQL 의경우만약클라이언트가로컬머신에있는 MySQL 서버에연결하려고시도하는경우 TCP/IP 를이용하지않고무조건유닉스소켓파일을이용합니다. 하지만만약 MySQL 서버는 /tmp/mysql.sock 파일을유닉스소켓으로만들었는데, mysql 등의클라이언트프로그램은 /usr/local/var/mysql.sock 파일의위치에서 mysql.sock 파일을찾으려고한다면 Can't connect to local MySQL server through socket '/usr/local/var/mysql.sock' 에러가발생할수있습니다. 따라서이런경우에는서로동일한위치에서 mysql.sock 파일을만들고사용하도록지정해야합니다. 또한 MySQL 서버가실행중이지않은경우도 mysql.sock 파일이생성되지않았으므로이에러가발생할수있습니다. 그러면이제앞에서설명드린각경우별로어떻게문제를해결할수있는지알아보겠습니다. i) MySQL 데몬이실행되지않은경우 MySQL 데몬이실행되지않은경우 mysql.sock 파일이생성되지않으므로이런에러가발생될수있습니다. 일단이에러가발생한경우에는 MySQL 데몬이실행중인지알아야합니다. 대부분의경우다음과같은명령으로 MySQL 데몬이실행중인지알수있습니다. [wertyu@inos ~]$ ps auxc grep mysqld root 1319 0.5 0.6 1712 852 pts/0 S 12:40 0:00 safe_mysqld root 1343 1.3 3.3 25436 4264 pts/0 S 12:40 0:00 mysqld root 1345 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 mysqld root 1346 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 mysqld 6
root 1347 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 mysqld 이러한결과가출력된다면현재 MySQL 데몬이실행중이라는것을알수있습니다. 만약 ps 의옵션으로 auxc 에서 c 옵션을주지않은경우에는 mysqld 프로그램의경로까지출력이되지만다음과같이실제프로그램명은출력이되지않으므로 grep 에서 mysqld 를찾지못할수있습니다. 다음은 ps aux 의결과인데프로그램의경로가길어서 mysqld 부분이짤린결과입니다. [wertyu@inos ~]$ ps aux.... root 1319 0.0 0.6 1712 852 pts/0 S 12:40 0:00 sh /usr/local/mys root 1343 0.1 3.3 25436 4264 pts/0 S 12:40 0:00 /usr/local/mysql/ root 1345 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 /usr/local/mysql/ root 1346 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 /usr/local/mysql/ root 1347 0.0 3.3 25436 4264 pts/0 S 12:40 0:00 /usr/local/mysql/ wertyu 1357 0.0 0.7 2552 924 pts/0 R 12:42 0:00 ps aux c 옵션은일단 mysqld 가실행중인지확인을한후에어느경로에서실행중인지알고싶을때는 c 옵션없이 ps 를실행하는것이좋습니다. 또한 netstat -a 명령으로다음과같이 MySQL 데몬이실행중인것을볼수있습니다. [wertyu@inos ~]$ netstat -a Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 *:mysql *:* LISTEN 필자의경우는 *:mysql 이라고출력이되었는데독자들의환경에따라서 *:3306 이라고출력되는경우도있으므로주의하시기바랍니다.( 이는 /etc/services 파일에서 MySQL 의서비스를지정하지않았기때문입니다.) MySQL 데몬이실행중인것을확인하였으면이제 Can't Connect 에러가발생하는이유는 MySQL 데몬이실행중이지않는이유가아니라는것을알수있으므로이유는다른문제에있으므로다음을계속읽어주시기바랍니다. 만약 MySQL 데몬이실행중이지않다면 MySQL 데몬을실행시켜주시고 MySQL 데몬을실행시킨후에도에러가계속발생한다면다음을계속해서읽어주세요. i) MySQL 데몬에서생성한 mysql.sock 파일과 mysql 등의클라이언트프로그램에서지정한 mysql.sock 파일의위치가서로다르다 앞에서 mysql.sock 파일이무엇인지어떤역할을하는지에대해서잠시설명을드렸습니다. 중요한것은 mysql.sock 파일은로컬의 MySQL 서버와클라이언트들이서로통신을하는데사용하는유닉스소켓파일인데만약 MySQL 서버에서는 mysql.sock 파일을 /tmp/mysql.sock 에만들었는데클라이언트파일은다른위치에서 mysql.sock 파일을찾으려한다면에러가발생한다는것입니다. 이문제를해결하기위해서는 MySQL 서버에서 mysql.sock 파일을만든위치를찾아야한다는것입니다. 그런후클라이언트프로그램을사용할때 -S 옵션 ( 혹은 --socket 옵션 ) 으로직접 mysql.sock 파일의위치를지정해주어야합니다. mysql.sock 파일을찾는가장간단한방법으로는 MySQL 을설치할때기본적으로포함되는 mysql_config 라는파일을이용하는것입니다. 만약 MySQL 을설치하고나서 mysql.sock 파일을위치를변경하지않았다면 mysql_config 프로그램으로 mysql.sock 파일의위치를찾을수 7
있습니다. [wertyu@inos bin]$ mysql_config --socket /tmp/mysql.sock 앞의결과는현재 MySQL 데몬은 mysql.sock 파일을 /tmp/mysql.sock 에만든다는것을나타냅니다. 하지만이결과는 MySQL 을사용하면서충분히바뀔수있는것이기때문에정확한답을출력하지않을수도있습니다. 더욱정확한답을찾기위해서는 netstat -ap 명령을실행하는것입니다. 다음은그결과입니다. [wertyu@inos bin]$ netstat -ap grep mysql (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 *:mysql *:* LISTEN - unix 0 [ ACC ] STREAM LISTENING 1596 - /tmp/mysql.sock 이결과를보면마지막에 LISTEN 이라는항목밑에 /tmp/mysql.sock 이라는것을볼수있습니다. 이말은현재 MySQL 이 /tmp/mysql.sock 파일에서연결을기다리고있다는말입니다. 이제 /tmp/mysql.sock 파일을찾으셨습니다. MySQL 이실행중이라면위의결과가나오지않는경우는없을것입니다. mysql.sock 파일이라는이름을사용하지않는경우에는 grep mysql 로검색이되지않으므로 grep mysql 없이 netstat -ap 의결과만으로손수찾아보시기바랍니다. 이렇게해서 mysql.sock 파일의위치를찾은경우에는클라이언트프로그램을사용할때 -S 옵션으로다음과같이 mysql.sock 파일의위치를직접지정해주어야합니다. [wertyu@inos bin]$ mysql -S/tmp/mysql.sock Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 3.23.32 Type 'help;' or '\h' for help. Type '\c' to clear the buffer mysql> 하지만 mysql 같은크라이언트프로그램에서는 -S 옵션으로 mysql.sock 파일을지정하면되지만 PHP 같은언어에서는어떻게지정할까요? MySQL C API 에서 MySQL 서버에연결할때사용하는 mysql_real_connect() 함수의가장마지막인자는 mysql.sock 파일의위치를지정하는옵션이므로이옵션을이용하면되고, PHP 에서는 PHP 의설정파일인 php.ini 파일에서다음과같은라인을찾아수정해주면됩니다. mysql.default_socket = 여기에앞에서찾은 mysql.sock 파일의위치를적은후에웹서버를재시작하면문제없이실행될것입니다. 다음과같이 mysqladmin 명령으로도 mysql.sock 파일의위치를알아낼수있습니다. [wertyu@inos ~]$ mysqladmin variables grep mysql.sock socket /tmp/mysql.sock 하지만문제는 mysqladmin 프로그램도 MySQL 클라이언트프로그램인지라이문제를해결하기전에는연결을할수없다는것입니다. 8
i) MySQL 데몬은실행중이나 mysql.sock 파일이지워졌다. 만약 MySQL 데몬도잘실행중이고 mysql.sock 파일의위치도알아내었은데계속해서문제가발생된다면 mysql.sock 파일이지워졌을가능성이있습니다. 서버를제대로설정했다면이런일을발생하지않지만가끔관리자의부주의혹은 MySQL 서버에이상이생긴경우또는크래커의장난등의이유로 mysql.sock 파일이지워지는경우가있습니다. 이런경우일단 ls 명령으로 mysql.sock 파일이존재하는지검사를한후정말로 mysql.sock 파일이없다면 MySQL 데몬의실행을중지한후재시작해야합니다. 주의해야할점은지금현재의문제가확실히 mysql.sock 파일이지워진것인지를알아야한다는것입니다. 만약 mysql.sock 파일이지워져서생긴문제가아니라면아무리재시작을해도문제가해결될리가없기때문입니다. 통상적으로 MySQL 데몬은 mysqladmin shutdown 명령으로실행을중지시킬수있지만 ( 그외방법으로아예시스템을재부팅해도됩니다 ) mysqladmin 프로그램도 MySQL 클라이언트프로그램이기때문에이문제가발생했을때는실행을시킬수가없을것입니다. 이경우에는다음과같은명령으로 MySQL 데몬의실행을중지시킬수있습니다. 다음에서 /path/to/mysql/data/directory 란 MySQL 의데이터디렉터리로이동하라는것을의미합니다. MySQL 의데이터디렉터리는 $ mysql admin variables grep datadir 명령으로확인할수있습니다. $ cd /path/to/mysql/data/directory $ kill `cat hostname.pid` 먼저 cd 명령으로 MySQL 의데이터디렉터리로이동합니다.( 데이터디렉터리가어딘지모르는독자는 ' 부록 1' 을참고하세요 ) 데이터디렉터리를보면 hostname.pid 라는파일이존재하는데이파일에현재 MySQL 의프로세스아이디가기록되어있습니다. 그후 kill `cat hostname.pid` 로 MySQL 데몬의실행을중지시킬수있습니다. 여기서 ` 는 ' 가아니라 ` 이니헷갈리지않기바랍니다. 2. PHP 에서의 MySQL 과관련된 Warning 메시지해결방법 PHP 로프로그래밍을하다보면다음과같은 Warning 메시지가출력되는경우를많이볼수있습니다. Warning: Supplied argument is not a valid MySQL-Link resource in /hd2/home/wertyu/public_html/error.php3 on line 4 Warning: Supplied argument is not a valid MySQL-Link resource in /hd2/home/wertyu/public_html/error.php3 on line 8 Warning: Supplied argument is not a valid MySQL result resource in /hd2/home/wertyu/public_html/error.php3 on line 10 대부분이런경우는프로그램내에서에러검사를전혀하지않았기때문입니다. 좋은프로그래머는항상함수를실행한뒤에에러검사를합니다. 아무리뛰어난프로그래머라도실수를할수있고, 시스템에이상이생겨서에러가발생할수있기때문이지요. 앞의 Warning 메시지들은다음의아주간단한프로그램내에서발생한메시지들입니다. 다음의소스와앞의메시지들로부터어떻게프로그램을작성해야좋은것인지에대해서알아보도록하겠습니다. 1 <? 9
2 $conn = mysql_connect("localhost", "wertyu", "pass") ; 3 4 mysql_select_db("nnr", $conn) ; 5 6 $query = "SELECT FROM student" ; 7 8 $result = mysql_query( $query, $conn) ; 9 10 $row = mysql_fetch_array( $result ) ; 11 12 echo $row["student_no"] ; 13 14?> 먼저앞의 Warning 메시지를보면 Supplied argument is not a valid MySQL-Link 라는말이나오는데이말을해석해보면 ' 입력된인자는올바른 MySQL 의연결이아니다 ' 라고해석을할수있습니다. 즉, 이 Warning 메시지는 mysql_connect() 함수에서연결이제대로되지않았기때문에발생하는 Warning 메시지라는것을알수있습니다. 그러면다음과같이 mysql_connect() 함수부분을에러검사를하도록수정해보겠습니다. $conn = mysql_connect("localhost", "wertyu", "pass") ; if( $conn == 0 ) { die( mysql_error() ) ; } 그런후다시실행을해보니 Warning: MySQL Connection Failed: Access denied for user: 'wertyu@localhost' (Using password: YES) in /hd2/home/wertyu/public_html/error.php3 on line 2 와같은에러가출력되면서프로그램이종료되었습니다. 즉, 지금까지문제를발생시켰던 Waring 메시지의원인중하나는연결을못하였기때문에발생하였다는것을알수있었습니다. 이제 mysql_connect() 함수에사용자명과암호를다시입력하여정확히연결을할수있도록다음과같이수정한후계속하여실행을해보았습니다. 1 <? 2 $conn = mysql_connect("localhost", "wertyu", "new_pass") ; 3 if( $conn == 0 ) 4 { 5 die( mysql_error() ) ; 6 } 7 8 mysql_select_db("nnr", $conn) ; 9 10 $query = "SELECT FROM student" ; 11 12 $result = mysql_query( $query, $conn) ; 13 14 $row = mysql_fetch_array( $result ) ; 15 16 echo $row["student_no"] ; 17 18?> 10
그랬더니이번에는다음과같은에러가발생하는군요. Warning: Supplied argument is not a valid MySQL result resource in /hd2/home/wertyu/public_html/error.php3 on line 14 이번에러를해석해보면, ' 입력된인자는옳바른 MySQL 의결과가아니다 ' 라고해석할수있습니다. 즉, 이말이의미하는것은 mysql_query() 함수를실행하여쿼리의결과를리턴하는데앞의예제에서 mysql_query() 함수에서이상이발생하였다는것을의미하는것입니다. 따라서이번에도 mysql_query() 함수에서에러검사를하는코드를다음과같이입력하시기바랍니다. $result = mysql_query( $query, $conn) ; if( $result == 0 ) { die( mysql_error() ) ; } 그런후다시실행을하니다음과같은 Warning 메시지가출력되었습니다. You have an error in your SQL syntax near 'FROM student' at line 1 아... mysql_query() 에서사용한 $query = "SELECT FROM student" 에서 SELECT 의문법이잘못되었군요. 이렇게에러검사를하면조금더쉽게에러를검사할수있습니다. 앞의예에서는쿼리가너무나간단하여쉽게눈으로도에러를검사할수있지마나몇줄에걸쳐있는쿼리들은에러를잡기가쉽지않습니다. Syntax 에러가발생하는경우, echo $query 와같이쿼리를직접출력해서확인하는것도좋은방법입니다. 그런데, 가끔쿼리를 mysql_query() 함수안에서정의하는분들이있는데, 이렇게되면, 쿼리를 echo 로출력할수없습니다. 따라서좋은습관은쿼리를 mysql_query() 함수밖에서정의하고, 함수의인자로넘기는방법입니다. 이렇게해야다음에 echo $query 로쿼리가어떻게되었는지눈으로확인하기쉽기때문에, Syntax 에러를쉽게찾을수있습니다. 자, 이제쿼리를수정도하고해서다음과같은 PHP 코드가만들어졌습니다. 1 <? 2 $conn = mysql_connect("localhost", "wertyu", "new_pass") ; 3 if( $conn == 0 ) 4 { 5 die( mysql_error() ) ; 6 } 7 8 mysql_select_db("nnr", $conn) ; 9 10 $query = "SELECT FROM student" ; 11 12 $result = mysql_query( $query, $conn) ; 13 if( $result == 0 ) 14 { 15 die( mysql_error() ) ; 16 } 17 18 $row = mysql_fetch_array( $result ) ; 19 20 echo $row["student_no"] ; 11
21 22?> 이제제대로실행되는지다시한번실행해봅시다. 이번에는제대로실행될줄알았는데이번에는다음과같은에러가출력되는군요. No Database Selected 독자의환경설정에따라다른메시지로출력되는경우가있습니다. 이번에는대체어디가잘못된것일까요? 잘한번맞춰보세요. 의심이가는곳이라고는딱한군데 mysql_select_db() 부분입니다. 그부분에서만에러검사를하지않았기때문입니다. 이제 mysql_select_db() 도다음과같이에러검사를하도록수정하시기바랍니다. if(! mysql_select_db("nnr", $conn) ) { die( mysql_error() ); } 위와같이 mysql_select_db() 함수에서도에러검사를하고실행을해보니다음과같은 Warning 메시지가출력되었습니다. Access denied for user: 'wertyu@localhost' to database 'nnr' 즉, 현재사용자는로긴을할수는있지만 nnr 이라는데이터베이스에접근을할수없었어서생기는문제였습니다. 이제 wertyu 사용자에게적절한권한을주고다시실행을시키면아무문제가없겠습니다. 최종완성된코드는다음과같습니다. 1 <? 2 $conn = mysql_connect("localhost", "wertyu", "new_pass") ; 3 if( $conn == 0 ) 4 { 5 die( mysql_error() ) ; 6 } 7 8 if(! mysql_select_db("nnr", $conn) ) 9 { 10 die( mysql_error() ); 11 } 12 13 $query = "SELECT * FROM student" ; 14 15 $result = mysql_query( $query, $conn) ; 16 if( $result == 0 ) 17 { 18 die( mysql_error() ) ; 19 } 20 21 $row = mysql_fetch_array( $result ) ; 22 23 echo $row["student_no"] ; 24 25?> 다시한번말씀드리지만훌륭한프로그래머는에러검사를정확히하여프로그램을오류가없도록만듭니다. 또한함수를사용할때도메뉴얼등을읽어가면서이함수의 return 값이 12
무엇인지, 함수호출이실패되었을경우에리턴되는값과성공하였을때리턴되는값을비교하여항상에러검사를합니다. 독자여러분들도에러검사를확실히하시기바랍니다. 마지막으로다음의에러를보겠습니다. Warning: Unable to jump to row 0 on MySQL result index 2 in /home/kimsh/public_html/sarang/res.php on line 6 Warning: Unable to jump to row 0 on MySQL result index 2 in /home/kimsh/public_html/sarang/res.php on line 7 Warning: Unable to jump to row 0 on MySQL result index 2 in /home/kimsh/public_html/sarang/res.php on line 8 5 : $dbresult = mysql_query("select * from res where res='result'",$dbconn); 6 : $rgood = mysql_result($dbresult,0,"good"); 7 : $rnormal = mysql_result($dbresult,0"normal"); 8 : $rbad = mysql_result($dbresult,0,"bad"); 이에러는 mysql_query() 에서함수를실행한후, mysql_result() 로레코드를하나씩가져오는데, 쿼리의결과로가져온레코드가하나도없는데, 레코드를가져오려고하기때문에발생하는에러입니다. 이런경우는 5번라인과 6번라인사이에, mysql_num_rows() 함수로몇개의레코드가있는지확인을한후, 1 개이상의레코드만있는경우, mysql_result() 함수를사용하도록고쳐야합니다. 그리고, 위에서도쿼리를 mysql_query() 함수안에서적었는데, 함수밖에서 query 를정의하고, echo $query 로어떤쿼리가실행되었는지눈으로확인한후에, 왜결과가없었는지보는것도좋은습관입니다. 13