[MDEV-11308] Read_only Clarification Created: 2016-11-18  Updated: 2017-01-30  Resolved: 2017-01-30

Status: Closed
Project: MariaDB Server
Component/s: Documentation, Locale Settings, Storage Engine - InnoDB
Affects Version/s: 10.1
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Chris Calender (Inactive) Assignee: Ian Gilfillan
Resolution: Fixed Votes: 0
Labels: None


 Description   

The manual states this about read_only option:

"Changing this to 1 will fail if you have table locks or transactions pending, while it will wait until other locks are released or transactions are completed."

https://mariadb.com/kb/en/mariadb/server-system-variables/#read_only

I have several issues with this sentence.

1. It almost seems contradictory, but if not, then it needs some further clarification.

For instance, it says, "Changing this to 1 will fail if you have ... transactions pending, while it will wait until other ... transactions are completed."

I'm not quite sure what the difference in a pending transaction and a transaction that is not yet completed but is working on being completed (perhaps it means the COMMIT was already issued?).

2. It says, "Changing this to 1 will fail if you have... transactions pending...".

In my tests, if I have a transaction pending, and I issue the "SET @@GLOBAL.read_only=1", then the SET commands takes effect, and then if I try to COMMIT the pending transaction, it fails. Thus this is the opposite of what the manual states.

I don't know if the manual is incorrect, or if the behavior from read_only is incorrect.

3. It says, "Changing this to 1 will fail if you have table locks... pending..."

Again, I tested this, and if I issue a TABLE LOCK on a table, and then issue SET @@GLOBAL.read_only=1" in another session, the SET command waits until you UNLOCK TABLES. So it does not fail either.

Again, I don't know if the manual is incorrect, or if the behavior from read_only is incorrect.

#2 test case:

Session #1:

mysql> select * from gtest;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+
4 rows in set (0.00 sec)
 
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into gtest (id) values (5);
Query OK, 1 row affected (0.03 sec)

Session #2:

mysql> set @@global.read_only=1;
Query OK, 0 rows affected (0.00 sec)

Session #1:

mysql> commit;
ERROR 1290 (HY000): The MariaDB server is running with the --read-only option so it cannot execute this statement
mysql>
mysql> select * from gtest;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+
4 rows in set (0.00 sec)

#3 test case:

Session #1:

mysql> lock table gtest write;
Query OK, 0 rows affected (0.00 sec)

Session #2:

mysql> set @@global.read_only=1;
...<hangs>...

Session #1:

mysql> insert into gtest (id) values (5);
Query OK, 1 row affected (0.03 sec)
 
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
 
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from gtest;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
5 rows in set (0.00 sec)
 
mysql> select version();
+-----------------+
| version()       |
+-----------------+
| 10.0.26-MariaDB |
+-----------------+
1 row in set (0.03 sec)

Session #2:

Query OK, 0 rows affected (35.18 sec)

(See how long it waited?)



 Comments   
Comment by Elena Stepanova [ 2016-11-18 ]

Regardless the rest of this comment, I agree with (1), it does sound confusing. I hope greenman can find a better wording for it.

I think the part about "pending" relates to your own session (yes, it's a bad choice of words). That's how it really looks (no other sessions are involved):

MariaDB [test]> lock table t1 write;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [test]> set global read_only=1;
ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction
MariaDB [test]> unlock tables;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [test]> set global read_only=1;
ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction
MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)

-- ensure there are no active transactions or locks
MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [test]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [test]> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)

If we agree that it accounts for the "if" part in this sentence

Changing this to 1 will fail if you have table locks or transactions pending, while it will wait until other locks are released or transactions are completed

the test case #3 seems to be working as expected, SET GLOBAL read_only waits until "other locks" are released.
So, what's left is "or transactions are completed". It does sound different from what we see (as described in test case #2). My best guess is that it's supposed to talk about statements, not about transactions; but it's just an empiric observation, for statements it does actually work.
Maybe jplindst can help clarifying it.

MySQL 5.6 manual has a bit different wording, but it does not explain anything either, and the behavior is the same as with MariaDB. It says "The attempt blocks if there are active transactions that hold metadata locks, until those transactions end.", which sounds clear enough, but it simply does not happen.

Assigning to jplindst for the opinion about "pending/active transactions". If everything appears to be working as expected, please reassign to greenman for fixing documentation.

Comment by Ian Gilfillan [ 2017-01-30 ]

I have clarified that "you" meant the current session, and also removed the mention of transactions that didn't seem to apply.

Generated at Thu Feb 08 07:48:57 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.