MySQL create table issue with --read-only error - mysql

I'd like to create a user who has all privileges with his own database in MySQL.
When I use this user to create a table, MySQL returns that the SQL server is running with read-only option.
However when I changed to an another existing user with all privileges on *.*, I can create table without error.
I'm wondering if the read-only option is global or what?
The following is my MySQL commands using MySQL root:
mysql> create user 'demo'#'localhost' identified by 'demo';
mysql> create database demo;
mysql> grant all privileges on demo.* to demo#localhost;
mysql> show grants for demo#localhost;
+-------------------------------------------------------------------------------------------------------------------+
| Grants for demo#localhost |
+-------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'demo'#'localhost' IDENTIFIED BY PASSWORD '*demo-hashed*' |
| GRANT ALL PRIVILEGES ON `demo`.* TO 'demo'#'localhost' |
+-------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Then I switched to user "demo":
mysql> use demo;
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> create table t(t1 int);
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
So I checked the read-only option, and it seems to be on.
However then I tried using another user with privileges on *.* and I can create tables successfully.
The another user grant setting:
mysql> show grants for demo2#'%';
+-----------------------------------------------------------------------------------------------------------------+
| Grants for demo2#% |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'demo2'#'%' IDENTIFIED BY PASSWORD '*demo2-hased*' |
+-----------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
MySQL version:
mysql> select version();
+------------------------+
| version() |
+------------------------+
| 5.1.68.0 |
+------------------------+
1 row in set (0.00 sec)
BTW, after I set read_only = 0 I can use demo to create table. I just don't know why the demo2 can create table while read-only is on.
Thanks!

Please check the My.cnf for Linux or My.ini for windows under [mysqld] remove read only parameters then restart the service and try again that will solve the read only problem, but if you create table in read only that will be a temp table.

Related

how do I grant a new user the privilege to create a new database in MySQL

how do I grant a new user the privilege to create a new database in MySQL
Specifically:
the database does not exist yet
I have successfuly created a new DB user account (that is not admin)
I want that non-admin user to create a new database
I do NOT want the 'admin' user to create the database and then grant privs to the database to the new user
as 'admin', I want to grant the new user the privilege to create a new database
I do not want to grant the new user any additional privileges on existing databases
This is not covered anywhere in the documentation that I can find.
Monday 2022-04-04
Update:
I created user 'scott' and then logged in as MySQL user 'admin' When I run this command
Note: The 'test' database does not yet exist
mysql>GRANT CREATE ON test.* to 'scott'#'localhost';
I get an error
==> ERROR 1410 (42000): You are not allowed to create a user with GRANT
Why do I get this error? I am not attempting to create a user, but rather grant a user access to a non-existent database (as is the approach with MySQL to grant a user privileges to create a database).
If up update the SQL statement to:
mysql>GRANT CREATE ON test.* to scott;
It runs OK
Query OK, 0 rows affected (0.07 sec)
And so now I login as user 'scott and run this statement:
mysql>create database rum;
==> ERROR 1049 (42000): Unknown database 'test'
Why do I get this error?
At this point, I am still not able to create a database as a non-admin user.
Example: grant "scott" the privilege to create the test3 database, which does not exist yet:
mysql> select user();
+----------------+
| user() |
+----------------+
| root#localhost |
+----------------+
mysql> grant create on test3.* to 'scott'#'localhost';
Query OK, 0 rows affected (0.01 sec)
Now try as scott to create the database:
mysql> select user();
+-----------------+
| user() |
+-----------------+
| scott#localhost |
+-----------------+
mysql> show grants;
+---------------------------------------------------------+
| Grants for scott#localhost |
+---------------------------------------------------------+
| GRANT USAGE ON *.* TO `scott`#`localhost` |
| GRANT ALL PRIVILEGES ON `test`.* TO `scott`#`localhost` |
| GRANT CREATE ON `test3`.* TO `scott`#`localhost` |
+---------------------------------------------------------+
mysql> create database test3;
Query OK, 1 row affected (0.00 sec)
mysql> use test3;
Database changed
MySQL has one privilege called CREATE which is for creating both databases and tables. See https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_create
You can either grant the user privilege to create a database of a specific name, or else grant them the privilege to create a database of any name, but that means they can also create other tables, either in the new database or in other existing databases. Sorry, there may not be a solution for you to allow them to create any new database without specifying the name when you grant the privilege, but then only have privilege in that database.
You are not allowed to create a user with GRANT
You did not create the user scott. Older versions of MySQL allows GRANT to implicitly create a user if one does not exist, but that has been disabled on more recent versions because folks realized it is a security weakness.
To be clear, the user "scott" is just an example I used. Don't literally use the name "scott" if that's not the user to whom you want to grant privileges.
The other errors you got seem to be that you granted the user privileges on a database named test.* but then you tried to create a database with a different name. The example I showed only grants the privilege to create the specific named database, not a database named rum or any other database.
I understand you want to grant privilege to create a database of any name. The syntax for that would be GRANT CREATE ON *.* TO... but that would grant the user privileges on all the other existing databases too.
There is no combination of syntax to grant privileges on any database name wildcard that means any database, provided that it is not yet created.

MySQL create use with permissions from anywhere fails

I'm trying to create a MySQL user with permissions from anywhere, but the command is failing:
MariaDB [(none)]> create user 'accounts'#'%' identified by 'password';
ERROR 1396 (HY000): Operation CREATE USER failed for 'accounts'#'%'
But if I change the permissions to access it from only localhost it works:
MariaDB [(none)]> CREATE USER 'accounts'#'localhost' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.01 sec)
I have a database called accounts:
MariaDB [(none)]> show databases like 'accounts';
+---------------------+
| Database (accounts) |
+---------------------+
| accounts |
+---------------------+
1 row in set (0.02 sec)
But I have to also create a user called accounts as well.
Note, I am doing this for work so I do not make decisions on who can access the DB from where.
Why does the first command fail?

Create database permission to user - Mysql access previleges

I want to create multiple users on MySQL and allow them to create databases and access the databases which are only created by them. Is there a way to do this?
If so what permission I need to give?
Instead of giving "create database" permission to a user, from "root" you can just create the database and grant all privileges on the database to the specific users. That's what I am using in my world. I don't think "create database" privileges available in MySQL especially.
Using the below approach you have the control of database level because the user can do anything in the specific database where they had the permission, not at the instance level (mean they can't create junk databases).
Friday 28> mysql -uroot -p
mysql> create user test identified by 'test';
mysql> create database x1;
mysql> grant all privileges on x1.* to 'test'#'%';
Friday 28> mysql -utest -p
Enter password:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| x1 |
+--------------------+
2 rows in set (0.00 sec)
mysql> use x1;
Database changed
mysql> create table test(c int);
seQuery OK, 0 rows affected (0.44 sec)
mysql> select * from test;
Empty set (0.00 sec)

Grant access to a user to create a database with a given name

I want to grant a user (my program) all access rights to a given database - read/write, even delete.
It is important that, after deletion (and, initially, before it ever exists), the user be able to create the database - but only with a given database name and the user should have no access to anything other than this database.
I am at a loss of the GRANT ...
The database does not have to exist to grant access to it. As a privileged user such as root you can do
mysql> grant all on dooda.* to 'dooda'#'localhost' identified by 'dooda';
mysql> exit
then
jason:>mysql -u dooda -p
Enter password:
etc
mysql> create database dooda;
Query OK, 1 row affected (0.00 sec)
but you can't
mysql> create database somethingelse;
ERROR 1044 (42000): Access denied for user 'dooda'#'localhost' to database 'somethingelse'
and if you
mysql> drop database dooda;
Query OK, 0 rows affected (0.00 sec)
mysql> create database dooda;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dooda |
| test |
+--------------------+

Why didn't MySQL GRANT create associated user accounts?

I installed Percona Toolkit to use pt-show-grants but it's not showing up all the grants. When I run it I see the following output:
-- Grants dumped by pt-show-grants
-- Dumped from server Localhost via UNIX socket, MySQL 5.5.43-log at 2015-06-11 09:19:19
-- Grants for 'bob'#'12.34.56.78'
GRANT SUPER ON *.* TO 'bob'#'12.34.56.78' IDENTIFIED BY PASSWORD '*4F72B97CAAAAAAAAAAA9C38064C4CCB18CA0DD8';
GRANT SELECT ON `mydb`.* TO 'bob'#'12.34.56.78';
...
In this case, bob is just a user. However all the web sites use specific credentials, for instance developer Bob might have an account for his example.com web site, called bob_examplecom_1. When I show the grants for this account:
mysql> SHOW GRANTS FOR 'bob_examplecom_1'#'localhost';
+-------------------------------------------------------------------------------------------------------------------------+
| Grants for bob_examplecom_1#localhost |
+-------------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'bob_examplecom_1'#'localhost' IDENTIFIED BY PASSWORD '*74AE8018AAAAAAAAAAAAAAAABB87B5C83E650CB' |
| GRANT ALL PRIVILEGES ON `bob_core`.* TO 'bob_examplecom_1'#'localhost' WITH GRANT OPTION |
| GRANT ALL PRIVILEGES ON `bob_examplecom_main`.* TO 'bob_examplecom_1'#'localhost' WITH GRANT OPTION |
| GRANT ALL PRIVILEGES ON `bob_blog`.* TO 'bob_examplecom_1'#'localhost' |
+-------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)
However, when I try find an associated user:
mysql> SELECT User, Host FROM mysql.user WHERE User LIKE 'bob\_%';
Empty set (0.00 sec)
Presumably the original GRANTs didn't create an associated user account? Also note that the above is an example of one web site, where there are many sites. I'm probably missing something here but I expected to see NO_AUTO_CREATE_USER in a mode:
mysql> SELECT ##GLOBAL.sql_mode;
+-------------------+
| ##GLOBAL.sql_mode |
+-------------------+
| |
+-------------------+
1 row in set (0.00 sec)
So, my problem is I want to use pt-show-grants to create an SQL file of the many GRANTs that need running for a new user on this development server, but I can't figure out how. Do I need to retrospectively create user accounts that match up to the GRANTs? Should I change some settings and/or setup accounts differently in the future?
Update: I just ran FLUSH PRIVILEGES and all the GRANTs that were working that had no associated accounts in mysql.user vanished. Does this mean they're gone for good, and all need to be recreated manually? Why would such a thing happen? I've looked through the MySQL command history and see no commands that would have dropped these accounts in the past. The uptime on this server is over 400 days and the sites have all worked in that time with little messing about.
Update 2: I had to recreate all the accounts. This time, with the GRANT USAGE and then granting privileges did indeed create the user accounts. My question is now a simple one:
Why didn't MySQL GRANT create associated user accounts when performing GRANTs?
Based on your description of the observed behavior, it sounds as if rows were removed from the mysql.user table, using a DELETE statement, rather than a DROP USER statement.
Changes made to the privilege tables (mysql.user, mysql.db, et al.) via DML statements (DELETE, INSERT, UPDATE), do not take effect immediately. MySQL has already read those tables, and the information is held in memory. Checks of privileges go against the in memory store; MySQL doesn't check the contents of the tables.
So it's possible to make changes to the mysql.user table, and not have those changes reflected in the effective privileges.
The FLUSH PRIVILEGES statement is what causes MySQL to re-read all the privilege tables, and rebuild the "in memory" store of privilege information.
To answer your question(s)...
Q: Presumably the original GRANTs didn't create an associated user account?
Q: Why didn't MySQL GRANT create associated user accounts when performing GRANTs?
A: The GRANT for a "new" user did create the user account, if it completed successfully. The appropriate row was added to the mysql.user table, and the privileges became effective (the change was also applied to the "in memory" privilege structure.
Q: Does this mean they're gone for good, and all need to be recreated manually?
A: Yes. If the rows are not in the mysql.user table, then those will need to be recreated. The rows in the mysql.user, mysql.db tables could be restored from a backup.
Q: Why would such a thing happen?
A: As mentioned earlier, someone may have inadvertently run a DELETE statement against mysql.user table. (It's also possible a TRUNCATE, or a DROP and CREATE. (Executing the SQL from mysqldump script that includes DROP TABLE statement, to reload the table from an old backup?)
If operations like that weren't performed on the table, then another possibility is that MyISAM table became corrupted, and the repair of the corruption caused the loss of rows. (A known issue with MyISAM tables; and one of the reasons we take backups of the databases, and test restores.)
Here's a demonstration of the behavior... removing a row from mysql.user is not immediately reflected in the effective privileges:
Verify user does not exist:
mysql> SELECT USER, HOST FROM mysql.user WHERE USER LIKE 'bob' ;
Empty set (0.00 sec)
mysql> SHOW GRANTS FOR 'bob'#'192.168.11.121' ;
ERROR 1141 (42000): There is no such grant defined for user 'bob' on host '192.168.11.121'
Create user with GRANT statement:
mysql> GRANT SELECT ON ergo.* TO 'bob'#'192.168.11.121' IDENTIFIED BY 'mysecret';
Query OK, 0 rows affected (0.00 sec)
Check contents of mysql.user table and effective privileges:
mysql> SELECT USER, HOST FROM mysql.user WHERE USER LIKE 'bob' ;
+------+----------------+
| USER | HOST |
+------+----------------+
| bob | 192.168.11.121 |
+------+----------------+
1 row in set (0.00 sec)
mysql> SHOW GRANTS FOR 'bob'#'192.168.11.121' ;
+-----------------------------------------------------------------------------------------------------------------+
| Grants for bob#192.168.11.121 |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'bob'#'192.168.11.121' IDENTIFIED BY PASSWORD '*440A4F469FD488A1C73204842936CC18A62A7D7F' |
| GRANT SELECT ON `ergo`.* TO 'bob'#'192.168.11.121' |
+-----------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Remove row from mysql.user table (using DML operation and not a DROP USER statement)
mysql> DELETE FROM mysql.user WHERE USER = 'bob' AND HOST = '192.168.11.121';
Query OK, 1 row affected (0.00 sec)
Row is gone from mysql.user table, but privileges are still effective:
mysql> SELECT USER, HOST FROM mysql.user WHERE USER LIKE 'bob' ;
Empty set (0.00 sec)
mysql> SHOW GRANTS FOR 'bob'#'192.168.11.121' ;
+-----------------------------------------------------------------------------------------------------------------+
| Grants for bob#192.168.11.121 |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'bob'#'192.168.11.121' IDENTIFIED BY PASSWORD '*440A4F469FD488A1C73204842936CC18A62A7D7F' |
| GRANT SELECT ON `ergo`.* TO 'bob'#'192.168.11.121' |
+-----------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Force MySQL to rebuild privileges, reading from mysql.user table...
mysql> FLUSH PRIVILEGES ;
Query OK, 0 rows affected (0.00 sec)
Privileges are no longer effective:
mysql> SHOW GRANTS FOR 'bob'#'192.168.11.121' ;
ERROR 1141 (42000): There is no such grant defined for user 'bob' on host '192.168.11.121'