backport dmitry.shulga@oracle.com-20120209125742-w7hdxv0103ymb8ko from mysql-trunk:
Patch for bug#11764747 (formerly known as 57612): SET GLOBAL READ_ONLY=1 cannot
progress when a table is locked with LOCK TABLES.
The reason for the bug was that mysql server makes a flush of all open tables
during handling of statement 'SET GLOBAL READ_ONLY=1'. Therefore if some of
these tables were locked by "LOCK TABLE ... READ" from a different connection,
then execution of statement 'SET GLOBAL READ_ONLY=1' would be waiting for
the lock for such table even if the table was locked in a compatible read mode.
Flushing of all open tables before setting of read_only system variable
is inherited from 5.1 implementation since this was the only possible approach
to ensure that there isn't any pending write operations on open tables.
Start from version 5.5 and above such behaviour is guaranteed by the fact
that we acquire global_read_lock before setting read_only flag. Since
acquiring of global_read_lock is successful only when there isn't any
active write operation then we can remove flushing of open tables from
processing of SET GLOBAL READ_ONLY=1.
This modification changes the server behavior so that read locks held
by other connections (LOCK TABLE ... READ) no longer will block attempts
to enable read_only.
Handle the 'set read_only=1' in lighter way, than the FLUSH TABLES READ LOCK;
For the transactional engines we don't wait for operations on that tables to finish.
per-file comments:
mysql-test/r/read_only_innodb.result
MDEV-136 Non-blocking "set read_only".
test result updated.
mysql-test/t/read_only_innodb.test
MDEV-136 Non-blocking "set read_only".
test case added.
sql/mysql_priv.h
MDEV-136 Non-blocking "set read_only".
The close_cached_tables_set_readonly() declared.
sql/set_var.cc
MDEV-136 Non-blocking "set read_only".
Call close_cached_tables_set_readonly() for the read_only::set_var.
sql/sql_base.cc
MDEV-136 Non-blocking "set read_only".
Parameters added to the close_cached_tables implementation,
close_cached_tables_set_readonly declared.
Prevent blocking on the transactional tables if the
set_readonly_mode is on.
* rename all debugging related command-line options
and variables to start from "debug-", and made them all
OFF by default.
* replace "MySQL" with "MariaDB" in error messages
* "Cast ... converted ... integer to it's ... complement"
is now a note, not a warning
* @@query_cache_strip_comments now has a session scope,
not global.
The problem was that in read only mode (read_only enabled),
the server would mistakenly deny data modification attempts
for temporary tables which belong to a transactional storage
engine (eg. InnoDB).
The solution is to allow transactional temporary tables to be
modified under read only mode. As a whole, the read only mode
does not apply to any kind of temporary table.
mysql-test/r/read_only_innodb.result:
Add test case result for Bug#33669
mysql-test/t/read_only_innodb.test:
Add test case for Bug#33669
sql/lock.cc:
Rename mysql_lock_tables_check to lock_tables_check and make
it static. Move locking related checks from get_lock_data to
lock_tables_check. Allow write locks to temporary tables even
under read-only.
Problem: SELECTs prohibited for a transactional SE in autocommit mode
if read_only is set.
Fix: allow them.
mysql-test/r/read_only_innodb.result:
Fix for bug #35732: read-only blocks SELECT statements in InnoDB
- test result.
mysql-test/t/read_only_innodb.test:
Fix for bug #35732: read-only blocks SELECT statements in InnoDB
- test case.
sql/handler.cc:
Fix for bug #35732: read-only blocks SELECT statements in InnoDB
- in autocommit mode thd->transaction.all list is empty thus
is_real_trans set to TRUE for any SELECTs, so using it in the
"read_only" check is insufficient.
ha_check_and_coalesce_trx_read_only() changed to return number
of engines with read-write changes. This value is used in the
"read-only" check and checks for GLOBAL READ LOCK.
sql/lock.cc:
Fix for bug #35732: read-only blocks SELECT statements in InnoDB
- added assert(protect_against_global_read_lock) before decreasing,
in order to catch (uint) 0 - 1 situation due to wrong
wait_if_global_read_lock()/start_waiting_global_read_lock() call
sequence.
Bug#11733 (COMMITs should not happen if read-only is set)
Bug#22009 (Can write to a read-only server under some circumstances)
See the work log for details
The change consist of
a) acquiring the global read lock in SET GLOBAL READONLY
b) honoring opt_readonly in ha_commit_trans(),
c) honoring opt_readonly in mysql_lock_tables().
a) takes care of the server stability,
b) makes the transactional tables safe (Bug 11733)
c) makes the non transactional tables safe (Bug 22009)
mysql-test/r/read_only.result:
WL#3602 (SET GLOBAL READONLY)
mysql-test/t/read_only.test:
WL#3602 (SET GLOBAL READONLY)
sql/handler.cc:
WL#3602 (SET GLOBAL READONLY)
sql/lock.cc:
WL#3602 (SET GLOBAL READONLY)
sql/set_var.cc:
WL#3602 (SET GLOBAL READONLY)
sql/set_var.h:
WL#3602 (SET GLOBAL READONLY)
mysql-test/r/read_only_innodb.result:
WL#3602 (SET GLOBAL READONLY)
mysql-test/t/read_only_innodb.test:
WL#3602 (SET GLOBAL READONLY)