Skip to content

Commit ce8a74f

Browse files
committed
MDEV-36425 Extend read_only to also block share locks and super user
The main purpose of this allow one to use the --read-only option to ensure that no one can issue a query that can block replication. The --read-only option can now take 4 different values: 0 No read only (as before). 1 Blocks changes for users without the 'READ ONLY ADMIN' privilege (as before). 2 Blocks in addition LOCK TABLES and SELECT IN SHARE MODE for not 'READ ONLY ADMIN' users. 3 Blocks in addition 'READ_ONLY_ADMIN' users for all the previous statements. read_only is changed to an enum and one can use the following names for the lock levels: OFF, ON, NO_LOCK, NO_LOCK_NO_ADMIN Too keep things compatible with older versions config files, one can still use values FALSE and TRUE, which are mapped to OFF and ON. The main visible changes are: - 'show variables like "read_only"' now returns a string instead of a number. - Error messages related to read_only violations now contains the current value off readonly. Other things: - is_read_only_ctx() renamed to check_read_only_with_error() - Moved TL_READ_SKIP_LOCKED to it's logical place Reviewed by: Sergei Golubchik <[email protected]>
1 parent 595e834 commit ce8a74f

37 files changed

+455
-171
lines changed

include/thr_lock.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ enum thr_lock_type { TL_IGNORE=-1,
4141
modify tables.
4242
*/
4343
TL_READ_DEFAULT,
44+
/* READ, but skip locks if found */
45+
TL_READ_SKIP_LOCKED,
4446
TL_READ, /* Read lock */
47+
/* Get shared locks on all read rows */
4548
TL_READ_WITH_SHARED_LOCKS,
4649
/* High prior. than TL_WRITE. Allow concurrent insert */
4750
TL_READ_HIGH_PRIORITY,
4851
/* READ, Don't allow concurrent insert */
4952
TL_READ_NO_INSERT,
50-
/* READ, but skip locks if found */
51-
TL_READ_SKIP_LOCKED,
52-
/*
53+
/*
5354
Write lock, but allow other threads to read / write.
5455
Used by BDB tables in MySQL to mark that someone is
5556
reading/writing to the table.
@@ -85,6 +86,9 @@ enum thr_lock_type { TL_IGNORE=-1,
8586
*/
8687
#define TL_FIRST_WRITE TL_WRITE_ALLOW_WRITE
8788

89+
/* First lock that can block readonly slaves using InnoDB tables */
90+
#define TL_BLOCKS_READONLY TL_READ_WITH_SHARED_LOCKS
91+
8892
enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1,
8993
THR_LOCK_WAIT_TIMEOUT= 2, THR_LOCK_DEADLOCK= 3 };
9094

mysql-test/main/alter_user.result

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ grant create user on *.* to foo;
3131
connect a, localhost, foo;
3232
select @@global.read_only;
3333
@@global.read_only
34-
1
34+
ON
3535
alter user foo;
36-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
36+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
3737
# Grant READ_ONLY ADMIN privilege to the user.
3838
connection default;
3939
grant READ_ONLY ADMIN on *.* to foo;

mysql-test/main/bug58669.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ SHOW VARIABLES LIKE "read_only%";
1414
Variable_name Value
1515
read_only ON
1616
INSERT INTO db1.t1 VALUES (1);
17-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
17+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
1818
connection default;
1919
disconnect con1;
2020
DROP DATABASE db1;

mysql-test/main/grant.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ Update Tables To update existing rows
637637
Set user Server To create views and stored routines with a different definer
638638
Federated admin Server To execute the CREATE SERVER, ALTER SERVER, DROP SERVER statements
639639
Connection admin Server To bypass connection limits and kill other users' connections
640-
Read_only admin Server To perform write operations even if @@read_only=ON
640+
Read_only admin Server To perform write operations even if @@read_only=READ_ONLY or READ_ONLY_NO_LOCK
641641
Usage Server Admin No privileges - allow connect only
642642
Show Create Routine Databases,Functions,Procedures To allow SHOW CREATE PROCEDURE/FUNCTION/PACKAGE
643643
connect root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK;

mysql-test/main/grant_read_only.result

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ SET @@GLOBAL.read_only=1;
1212
connect con1,localhost,user1,,;
1313
connection con1;
1414
UPDATE t1 SET a=11 WHERE a=10;
15-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
15+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
1616
DELETE FROM t1 WHERE a=11;
17-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
17+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
1818
INSERT INTO t1 VALUES (20);
19-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
19+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
2020
disconnect con1;
2121
connection default;
2222
SET @@GLOBAL.read_only=0;
@@ -36,7 +36,7 @@ connect con1,localhost,user1,,;
3636
connection con1;
3737
SELECT @@read_only;
3838
@@read_only
39-
1
39+
ON
4040
UPDATE t1 SET a=11 WHERE a=10;
4141
DELETE FROM t1 WHERE a=11;
4242
INSERT INTO t1 VALUES (20);
@@ -59,11 +59,11 @@ connect con1,localhost,user1,,;
5959
connection con1;
6060
SELECT @@read_only;
6161
@@read_only
62-
1
62+
ON
6363
UPDATE t1 SET a=11 WHERE a=10;
64-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
64+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
6565
DELETE FROM t1 WHERE a=11;
66-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
66+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
6767
connection default;
6868
grant read only admin on *.* to user1@localhost;
6969
disconnect con1;

mysql-test/main/mysqld--help.result

+8-4
Original file line numberDiff line numberDiff line change
@@ -1154,9 +1154,13 @@ The following specify which files/extra groups are read (specified before remain
11541154
buffer of this size for each table it scans. If you do
11551155
many sequential scans, you may want to increase this
11561156
value
1157-
--read-only Make all non-temporary tables read-only, with the
1158-
exception for replication (slave) threads and users with
1159-
the 'READ ONLY ADMIN' privilege
1157+
--read-only[=name] Do not allow changes to non-temporary tables. Options
1158+
are:OFF changes allowed. ON Disallow changes for users
1159+
without the READ ONLY ADMIN privilege. NO_LOCK
1160+
Additionally disallows LOCK TABLES and SELECT IN SHARE
1161+
MODE. NO_LOCK_NO_ADMIN Disallows also for users with
1162+
READ_ONLY ADMIN privilege. Replication (slave) threads
1163+
are not affected by this option
11601164
--read-rnd-buffer-size=#
11611165
When reading rows in sorted order after a sort, the rows
11621166
are read through this buffer to avoid a disk seeks
@@ -1972,7 +1976,7 @@ query-prealloc-size 32768
19721976
range-alloc-block-size 4096
19731977
read-binlog-speed-limit 0
19741978
read-buffer-size 131072
1975-
read-only FALSE
1979+
read-only OFF
19761980
read-rnd-buffer-size 262144
19771981
redirect-url
19781982
relay-log (No default value)

mysql-test/main/read_only.result

+134-24
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,31 @@ drop table t3;
1818
connection con1;
1919
select @@global.read_only;
2020
@@global.read_only
21-
1
21+
ON
2222
create table t3 (a int);
23-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
23+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
2424
insert into t1 values(1);
25-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
25+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
2626
drop trigger trg1;
27-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
27+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
2828
update t1 set a=1 where 1=0;
29-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
29+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
3030
update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a;
31-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
31+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
3232
delete t1,t2 from t1,t2 where t1.a=t2.a;
33-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
33+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
3434
create temporary table t3 (a int);
3535
create temporary table t4 (a int) select * from t3;
3636
insert into t3 values(1);
3737
insert into t4 select * from t3;
3838
create table t3 (a int);
39-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
39+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
4040
update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a;
41-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
41+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
4242
update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a;
4343
update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a;
4444
delete t1 from t1,t3 where t1.a=t3.a;
45-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
45+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
4646
delete t3 from t1,t3 where t1.a=t3.a;
4747
delete t4 from t3,t4 where t4.a=t3.a;
4848
create temporary table t1 (a int);
@@ -51,7 +51,7 @@ update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a;
5151
delete t1 from t1,t3 where t1.a=t3.a;
5252
drop table t1;
5353
insert into t1 values(1);
54-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
54+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
5555
drop temporary table if exists t1;
5656
Warnings:
5757
Note 1051 Unknown table 'test.t1'
@@ -69,11 +69,11 @@ set global read_only=1;
6969
connection con1;
7070
select @@global.read_only;
7171
@@global.read_only
72-
0
72+
OFF
7373
unlock tables ;
7474
select @@global.read_only;
7575
@@global.read_only
76-
1
76+
ON
7777
connection default;
7878
reap;
7979
connection default;
@@ -88,11 +88,11 @@ unlock tables ;
8888
set global read_only=1;
8989
select @@global.read_only;
9090
@@global.read_only
91-
1
91+
ON
9292
connection con1;
9393
select @@global.read_only;
9494
@@global.read_only
95-
1
95+
ON
9696
unlock tables ;
9797
connection default;
9898
connection default;
@@ -108,7 +108,7 @@ set global read_only=1;
108108
connection con1;
109109
select @@global.read_only;
110110
@@global.read_only
111-
1
111+
ON
112112
ROLLBACK;
113113
connection default;
114114
set global read_only=0;
@@ -124,7 +124,7 @@ set global read_only=1;
124124
connection default;
125125
select @@global.read_only;
126126
@@global.read_only
127-
1
127+
ON
128128
unlock tables;
129129
disconnect root2;
130130
drop temporary table ttt;
@@ -157,11 +157,11 @@ flush privileges;
157157
connect con_bug27440,127.0.0.1,mysqltest_u1,,test,$MASTER_MYPORT,;
158158
connection con_bug27440;
159159
create database mysqltest_db2;
160-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
160+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
161161
show databases like '%mysqltest_db2%';
162162
Database (%mysqltest_db2%)
163163
drop database mysqltest_db1;
164-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
164+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
165165
disconnect con_bug27440;
166166
connection default;
167167
delete from mysql.user where User like 'mysqltest_%';
@@ -179,7 +179,7 @@ GRANT ALTER ON test1.* TO user1@localhost;
179179
CREATE DATABASE test1;
180180
SET GLOBAL read_only=1;
181181
ALTER DATABASE test1 CHARACTER SET utf8;
182-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
182+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
183183
SET GLOBAL read_only=0;
184184
DROP DATABASE test1;
185185
DROP USER user1@localhost;
@@ -210,21 +210,131 @@ connection con1;
210210
START TRANSACTION;
211211
# Check that table updates are still disallowed.
212212
INSERT INTO t1 VALUES (3);
213-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
213+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
214214
UPDATE t1 SET a= 1;
215-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
215+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
216216
DELETE FROM t1;
217-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
217+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
218218
COMMIT;
219219
START TRANSACTION READ ONLY;
220220
COMMIT;
221221
# Explicit RW trans is not allowed without super privilege
222222
START TRANSACTION READ WRITE;
223-
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
223+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
224224
COMMIT;
225225
disconnect con1;
226226
connection default;
227227
DROP USER user1;
228228
SET GLOBAL read_only= 0;
229229
DROP TABLE t1;
230230
# End of 10.0 tests
231+
#
232+
# MDEV-36425 Extend read_only to also block share locks and super user
233+
#
234+
CREATE USER user1;
235+
GRANT ALL on test.* to user1;
236+
connect con1, localhost, user1;
237+
connection default;
238+
CREATE TABLE t1 (a int primary key auto_increment);
239+
insert into t1 values (1),(2);
240+
show variables like "read_only";
241+
Variable_name Value
242+
read_only OFF
243+
SET GLOBAL read_only=1;
244+
show variables like "read_only";
245+
Variable_name Value
246+
read_only ON
247+
# admin
248+
insert into t1 values ();
249+
lock tables t1 read;
250+
unlock tables;
251+
lock tables t1 write;
252+
unlock tables;
253+
begin;
254+
select count(*) from t1 LOCK IN SHARE MODE;
255+
count(*)
256+
3
257+
select count(*) from t1,(select a from t1 LOCK IN SHARE MODE) as t2;
258+
count(*)
259+
9
260+
commit;
261+
# user
262+
connection con1;
263+
insert into t1 values ();
264+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
265+
lock tables t1 read;
266+
unlock tables;
267+
lock tables t1 write;
268+
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
269+
unlock tables;
270+
begin;
271+
select count(*) from t1 LOCK IN SHARE MODE;
272+
count(*)
273+
3
274+
select count(*) from t1,(select a from t1 LOCK IN SHARE MODE) as t2;
275+
count(*)
276+
9
277+
commit;
278+
connection default;
279+
SET GLOBAL read_only=2;
280+
show variables like "read_only";
281+
Variable_name Value
282+
read_only NO_LOCK
283+
# admin
284+
insert into t1 values ();
285+
lock tables t1 read;
286+
unlock tables;
287+
lock tables t1 write;
288+
unlock tables;
289+
begin;
290+
select count(*) from t1 LOCK IN SHARE MODE;
291+
count(*)
292+
4
293+
select count(*) from t1,(select a from t1 LOCK IN SHARE MODE) as t2;
294+
count(*)
295+
16
296+
commit;
297+
#user
298+
connection con1;
299+
insert into t1 values ();
300+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK option so it cannot execute this statement
301+
lock tables t1 read;
302+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK option so it cannot execute this statement
303+
unlock tables;
304+
lock tables t1 write;
305+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK option so it cannot execute this statement
306+
unlock tables;
307+
begin;
308+
select count(*) from t1 LOCK IN SHARE MODE;
309+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK option so it cannot execute this statement
310+
select count(*) from t1,(select a from t1 LOCK IN SHARE MODE) as t2;
311+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK option so it cannot execute this statement
312+
commit;
313+
connection default;
314+
SET GLOBAL read_only=3;
315+
show variables like "read_only";
316+
Variable_name Value
317+
read_only NO_LOCK_NO_ADMIN
318+
# admin
319+
insert into t1 values ();
320+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK_NO_ADMIN option so it cannot execute this statement
321+
lock tables t1 read;
322+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK_NO_ADMIN option so it cannot execute this statement
323+
unlock tables;
324+
lock tables t1 write;
325+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK_NO_ADMIN option so it cannot execute this statement
326+
unlock tables;
327+
begin;
328+
select count(*) from t1 LOCK IN SHARE MODE;
329+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK_NO_ADMIN option so it cannot execute this statement
330+
select count(*) from t1,(select a from t1 LOCK IN SHARE MODE) as t2;
331+
ERROR HY000: The MariaDB server is running with the --read-only=NO_LOCK_NO_ADMIN option so it cannot execute this statement
332+
commit;
333+
SET GLOBAL read_only=0;
334+
select count(*) from t1;
335+
count(*)
336+
4
337+
drop table t1;
338+
drop user user1;
339+
disconnect con1;
340+
# End of 11.8 tests

0 commit comments

Comments
 (0)