The world's most popular open source database
You can create MySQL accounts in two ways:
By using statements intended for creating accounts, such as
CREATE USER or
GRANT
By manipulating the MySQL grant tables directly with
statements such as INSERT,
UPDATE, or
DELETE
The preferred method is to use account-creation statements because
they are more concise and less error-prone.
CREATE USER and
GRANT are described in
Section 12.5.1.1, “CREATE USER Syntax”, and Section 12.5.1.3, “GRANT Syntax”.
Another option for creating accounts is to use one of several
available third-party programs that offer capabilities for MySQL
account administration. phpMyAdmin is one such
program.
The following examples show how to use the
mysql client program to set up new users. These
examples assume that privileges are set up according to the
defaults described in Section 2.10.3, “Securing the Initial MySQL Accounts”. This
means that to make changes, you must connect to the MySQL server
as the MySQL root user, and the
root account must have the
INSERT privilege for the
mysql database and the
RELOAD administrative privilege.
As noted in the examples where appropriate, some of the statements
will fail if you have the server's SQL mode has been set to enable
certain restrictions. In particular, strict mode
(STRICT_TRANS_TABLES,
STRICT_ALL_TABLES) and
NO_AUTO_CREATE_USER will prevent
the server from accepting some of the statements. Workarounds are
indicated for these cases. For more information about SQL modes
and their effect on grant table manipulation, see
Section 5.1.7, “Server SQL Modes”, and Section 12.5.1.3, “GRANT Syntax”.
First, use the mysql program to connect to the
server as the MySQL root user:
shell> mysql --user=root mysql
If you have assigned a password to the root
account, you'll also need to supply a --password
or -p option for this mysql
command and also for those later in this section.
After connecting to the server as root, you can
add new accounts. The following statements use
GRANT to set up four new accounts:
mysql>GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'->IDENTIFIED BY 'some_pass' WITH GRANT OPTION;mysql>GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'->IDENTIFIED BY 'some_pass' WITH GRANT OPTION;mysql>GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';mysql>GRANT USAGE ON *.* TO 'dummy'@'localhost';
The accounts created by these GRANT
statements have the following properties:
Two of the accounts have a username of
monty and a password of
some_pass. Both accounts are superuser
accounts with full privileges to do anything. One account
('monty'@'localhost') can be used only when
connecting from the local host. The other
('monty'@'%') can be used to connect from
any other host. Note that it is necessary to have both
accounts for monty to be able to connect
from anywhere as monty. Without the
localhost account, the anonymous-user
account for localhost that is created by
mysql_install_db would take precedence when
monty connects from the local host. As a
result, monty would be treated as an
anonymous user. The reason for this is that the anonymous-user
account has a more specific Host column
value than the 'monty'@'%' account and thus
comes earlier in the user table sort order.
(user table sorting is discussed in
Section 5.4.4, “Access Control, Stage 1: Connection Verification”.)
One account has a username of admin and no
password. This account can be used only by connecting from the
local host. It is granted the
RELOAD and
PROCESS administrative
privileges. These privileges allow the
admin user to execute the
mysqladmin reload, mysqladmin
refresh, and mysqladmin
flush-xxx commands, as
well as mysqladmin processlist . No
privileges are granted for accessing any databases. You could
add such privileges later by issuing additional
GRANT statements.
One account has a username of dummy and no
password. This account can be used only by connecting from the
local host. No privileges are granted. The
USAGE privilege in the
GRANT statement enables you to
create an account without giving it any privileges. It has the
effect of setting all the global privileges to
'N'. It is assumed that you will grant
specific privileges to the account later.
The statements that create accounts with no password will fail
if the NO_AUTO_CREATE_USER
SQL mode is enabled. To deal with this, use an
IDENTIFIED BY clause that specifies a
non-empty password.
As an alternative to GRANT, you can
create the same accounts directly by issuing
INSERT statements and then telling
the server to reload the grant tables using
FLUSH PRIVILEGES:
shell>mysql --user=root mysqlmysql>INSERT INTO user->VALUES('localhost','monty',PASSWORD('some_pass'),->'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');mysql>INSERT INTO user->VALUES('%','monty',PASSWORD('some_pass'),->'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',->'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',->'','','','',0,0,0,0);mysql>INSERT INTO user SET Host='localhost',User='admin',->Reload_priv='Y', Process_priv='Y';mysql>INSERT INTO user (Host,User,Password)->VALUES('localhost','dummy','');mysql>FLUSH PRIVILEGES;
The reason for using FLUSH
PRIVILEGES when you create accounts with
INSERT is to tell the server to
re-read the grant tables. Otherwise, the changes go unnoticed
until you restart the server. With
GRANT,
FLUSH PRIVILEGES
is unnecessary.
The reason for using the PASSWORD()
function with INSERT is to encrypt
the password. The GRANT statement
encrypts the password for you, so
PASSWORD() is unnecessary.
The 'Y' values enable privileges for the
accounts. Depending on your MySQL version, you may have to use a
different number of 'Y' values in the first two
INSERT statements. For the
admin account, you may also employ the more
readable extended INSERT syntax
using SET.
In the INSERT statement for the
dummy account, only the
Host, User, and
Password columns in the user
table row are assigned values. None of the privilege columns are
set explicitly, so MySQL assigns them all the default value of
'N'. This is equivalent to what GRANT
USAGE does.
If strict SQL mode is enabled, all columns that have no default
value must have a value specified. In this case,
INSERT statements must explicitly
specify values for the
ssl_cipher,
x509_issuer, and
x509_subject columns.
Note that to set up a superuser account, it is necessary only to
create a user table entry with the privilege
columns set to 'Y'. user
table privileges are global, so no entries in any of the other
grant tables are needed.
The next examples create three accounts and give them access to
specific databases. Each of them has a username of
custom and password of
obscure.
To create the accounts with GRANT,
use the following statements:
shell>mysql --user=root mysqlmysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP->ON bankaccount.*->TO 'custom'@'localhost'->IDENTIFIED BY 'obscure';mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP->ON expenses.*->TO 'custom'@'whitehouse.gov'->IDENTIFIED BY 'obscure';mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP->ON customer.*->TO 'custom'@'server.domain'->IDENTIFIED BY 'obscure';
The three accounts can be used as follows:
The first account can access the
bankaccount database, but only from the
local host.
The second account can access the expenses
database, but only from the host
whitehouse.gov.
The third account can access the customer
database, but only from the host
server.domain.
To set up the custom accounts without
GRANT, use
INSERT statements as follows to
modify the grant tables directly:
shell>mysql --user=root mysqlmysql>INSERT INTO user (Host,User,Password)->VALUES('localhost','custom',PASSWORD('obscure'));mysql>INSERT INTO user (Host,User,Password)->VALUES('whitehouse.gov','custom',PASSWORD('obscure'));mysql>INSERT INTO user (Host,User,Password)->VALUES('server.domain','custom',PASSWORD('obscure'));mysql>INSERT INTO db->(Host,Db,User,Select_priv,Insert_priv,->Update_priv,Delete_priv,Create_priv,Drop_priv)->VALUES('localhost','bankaccount','custom',->'Y','Y','Y','Y','Y','Y');mysql>INSERT INTO db->(Host,Db,User,Select_priv,Insert_priv,->Update_priv,Delete_priv,Create_priv,Drop_priv)->VALUES('whitehouse.gov','expenses','custom',->'Y','Y','Y','Y','Y','Y');mysql>INSERT INTO db->(Host,Db,User,Select_priv,Insert_priv,->Update_priv,Delete_priv,Create_priv,Drop_priv)->VALUES('server.domain','customer','custom',->'Y','Y','Y','Y','Y','Y');mysql>FLUSH PRIVILEGES;
The first three INSERT statements
add user table entries that allow the user
custom to connect from the various hosts with
the given password, but grant no global privileges (all privileges
are set to the default value of 'N'). The next
three INSERT statements add
db table entries that grant privileges to
custom for the bankaccount,
expenses, and customer
databases, but only when accessed from the proper hosts. As usual
when you modify the grant tables directly, you must tell the
server to reload them with
FLUSH PRIVILEGES
so that the privilege changes take effect.
If you want to give a specific user access from all machines in a
given domain (for example, mydomain.com), you
can issue a GRANT statement that
uses the “%” wildcard character in
the host part of the account name:
mysql>GRANT ...->ON *.*->TO 'myname'@'%.mydomain.com'->IDENTIFIED BY 'mypass';
To do the same thing by modifying the grant tables directly, do this:
mysql>INSERT INTO user (Host,User,Password,...)->VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...);mysql>FLUSH PRIVILEGES;


User Comments
WARNING: ~/.mysql_history shows any PASSWORD('xxx') calls.
Just a note to admins and users out there; be sure to chmod
0600 your ~/.mysql_history as well as any ~/.my.cnf files.
Otherwise anyone with a local account might be able to read any
of your GRANT and SET PASSWORD statements.
Indeed one solution to your password problem could lie in the value of 'host'.
Check it out by issuing "SELECT user()" using different interfaces (CLI, web server), and giving different values for 'host'.
On one server where I'm not admin but I have to work on, there happen strange things :
sometimes host='' defaults to 'localhost', sometimes to 'localhost.localdomain' (on the same mysql server !!) and the two corresponding accounts can have different passwords.
Or one may need a password, and the other one not.
Even worse, on this server:
<?phpmysql_connect('localhost');
print_r( mysql_fetch_assoc( mysql_query( "SELECT user()")))
?>
shows:
Array ( [user()] => nobody@localhost.localdomain )
i.e. it is IMPOSSIBLE to connect from PHP with host='localhost', while the CLI shows that there exist two different users,
nobody@localhost and nobody@localhost.localdomain
(and its the same for user='root'! and they have different privileges!)
In general, phpMyAdmin will do what you need for your PHP scripts, because it uses the same interface (as long as they run on the same web server), while the CLI does not (but allows for more direct and less 'default prone' access to the db server).
Also keep in mind the VARIOUS security risks using phpMyAdmin (among others, both Apache HTTP_AUTH passwords and MySQL passwords transit in clear text in the POST data, and might be available to 'everybody' as global variables (eg. if register_globals is on) ...) !
Say you wanted to add a couple of users,
but wanted to prevent access to the entire db to one of them -
mysql> grant all on DATABASENAME to USERNAME1 identified by 'PASSWORD';
This allows them all privs, but only to that database.
To restrict privs:
mysql>grant select (FIELD1, FIELD2) on DATABASENAME to USERNAME2 identified by 'PASSWORD';
Add your own comment.