Below is the list of changes that have just been committed into a local
5.1 repository of marcsql. When marcsql does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-11-10 20:17:44-07:00, malff@weblab.(none) +8 -0
WL#3602 (SET GLOBAL READONLY)
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@stripped, 2006-11-10 20:17:42-07:00, malff@weblab.(none) +45 -1
WL#3602 (SET GLOBAL READONLY)
mysql-test/r/read_only_innodb.result@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none)
+18 -0
WL#3602 (SET GLOBAL READONLY)
mysql-test/r/read_only_innodb.result@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none)
+0 -0
mysql-test/t/read_only.test@stripped, 2006-11-10 20:17:42-07:00, malff@weblab.(none) +92 -2
WL#3602 (SET GLOBAL READONLY)
mysql-test/t/read_only_innodb.test@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none)
+43 -0
WL#3602 (SET GLOBAL READONLY)
mysql-test/t/read_only_innodb.test@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none)
+0 -0
sql/handler.cc@stripped, 2006-11-10 20:17:42-07:00, malff@weblab.(none) +9 -0
WL#3602 (SET GLOBAL READONLY)
sql/lock.cc@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none) +13 -0
WL#3602 (SET GLOBAL READONLY)
sql/set_var.cc@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none) +31 -1
WL#3602 (SET GLOBAL READONLY)
sql/set_var.h@stripped, 2006-11-10 20:17:43-07:00, malff@weblab.(none) +14 -0
WL#3602 (SET GLOBAL READONLY)
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: malff
# Host: weblab.(none)
# Root: /home/marcsql/TREE/mysql-5.1-11733_topdown
--- 1.278/sql/handler.cc 2006-11-10 20:17:50 -07:00
+++ 1.279/sql/handler.cc 2006-11-10 20:17:50 -07:00
@@ -692,6 +692,15 @@ int ha_commit_trans(THD *thd, bool all)
ha_rollback_trans(thd, all);
DBUG_RETURN(1);
}
+
+ if (is_real_trans && opt_readonly)
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+ ha_rollback_trans(thd, all);
+ error= 1;
+ goto end;
+ }
+
DBUG_EXECUTE_IF("crash_commit_before", abort(););
/* Close all cursors that can not survive COMMIT */
--- 1.98/sql/lock.cc 2006-11-10 20:17:50 -07:00
+++ 1.99/sql/lock.cc 2006-11-10 20:17:50 -07:00
@@ -127,6 +127,19 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
&write_lock_used)))
break;
+ if (write_lock_used && opt_readonly)
+ {
+ /*
+ Someone has issued SET GLOBAL READONLY=1 and we want a write lock.
+ We do not wait for READONLY=0, and fail.
+ */
+ reset_lock_data(sql_lock);
+ my_free((gptr) sql_lock, MYF(0));
+ sql_lock=0;
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+ break;
+ }
+
if (global_read_lock && write_lock_used &&
! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
{
--- 1.3/mysql-test/r/read_only.result 2006-11-10 20:17:50 -07:00
+++ 1.4/mysql-test/r/read_only.result 2006-11-10 20:17:50 -07:00
@@ -39,6 +39,50 @@ delete t1 from t1,t3 where t1.a=t3.a;
drop table t1;
insert into t1 values(1);
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute
this statement
+set global read_only=0;
+lock table t1 write;
+lock table t2 write;
+set global read_only=1;
+ERROR HY000: Can't execute the given command because you have active locked tables or an
active transaction
+unlock tables ;
+set global read_only=1;
+select @@global.read_only;
+@@global.read_only
+1
+unlock tables ;
+set global read_only=0;
+lock table t1 read;
+lock table t2 read;
+set global read_only=1;
+ERROR HY000: Can't execute the given command because you have active locked tables or an
active transaction
+unlock tables ;
+set global read_only=1;
+select @@global.read_only;
+@@global.read_only
+1
+unlock tables ;
+set global read_only=0;
+BEGIN;
+BEGIN;
+set global read_only=1;
+ERROR HY000: Can't execute the given command because you have active locked tables or an
active transaction
+ROLLBACK;
+set global read_only=1;
+select @@global.read_only;
+@@global.read_only
+1
+ROLLBACK;
+set global read_only=0;
+flush tables with read lock;
+set global read_only=1;
+unlock tables;
+set global read_only=0;
+flush tables with read lock;
+set global read_only=1;
+select @@global.read_only;
+@@global.read_only
+1
+unlock tables;
+set global read_only=0;
drop table t1,t2;
drop user test@localhost;
-set global read_only=0;
--- 1.4/mysql-test/t/read_only.test 2006-11-10 20:17:50 -07:00
+++ 1.5/mysql-test/t/read_only.test 2006-11-10 20:17:50 -07:00
@@ -101,8 +101,98 @@ drop table t1;
--error 1290
insert into t1 values(1);
+#
+# BUG#11733: COMMITs should not happen if read-only is set
+#
+
+# LOCK TABLE ... WRITE / READ_ONLY
+# - is an error in the same connection
+# - is ok in a different connection
+
connection default;
-drop table t1,t2;
-drop user test@localhost;
+set global read_only=0;
+lock table t1 write;
+
+connection con1;
+lock table t2 write;
+
+connection default;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+set global read_only=1;
+unlock tables ;
+set global read_only=1;
+
+connection con1;
+select @@global.read_only;
+unlock tables ;
+
+# LOCK TABLE ... READ / READ_ONLY
+# - is an error in the same connection
+# - is ok in a different connection
+connection default;
+set global read_only=0;
+lock table t1 read;
+
+connection con1;
+lock table t2 read;
+
+connection default;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+set global read_only=1;
+unlock tables ;
+set global read_only=1;
+
+connection con1;
+select @@global.read_only;
+unlock tables ;
+
+# pending transaction / READ_ONLY
+# - is an error in the same connection
+# - is ok in a different connection
+
+connection default;
set global read_only=0;
+BEGIN;
+
+connection con1;
+BEGIN;
+
+connection default;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+set global read_only=1;
+ROLLBACK;
+set global read_only=1;
+
+connection con1;
+select @@global.read_only;
+ROLLBACK;
+
+# Verify that FLUSH TABLES WITH READ LOCK do not block READ_ONLY
+# - in the same SUPER connection
+# - in another SUPER connection
+
+connection default;
+set global read_only=0;
+flush tables with read lock;
+set global read_only=1;
+unlock tables;
+
+connect (root2,localhost,root,,test);
+
+connection default;
+set global read_only=0;
+flush tables with read lock;
+
+connection root2;
+set global read_only=1;
+
+connection default;
+select @@global.read_only;
+unlock tables;
+
+# Cleanup
+connection default;
+set global read_only=0;
+drop table t1,t2;
+drop user test@localhost;
--- New file ---
+++ mysql-test/r/read_only_innodb.result 06/11/10 20:17:43
DROP TABLE IF EXISTS table_11733 ;
grant CREATE, SELECT, DROP on *.* to test@localhost;
set global read_only=0;
create table table_11733 (a int) engine=InnoDb;
BEGIN;
insert into table_11733 values(11733);
set global read_only=1;
select @@global.read_only;
@@global.read_only
1
select * from table_11733 ;
a
11733
COMMIT;
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute
this statement
set global read_only=0;
drop table table_11733 ;
drop user test@localhost;
--- New file ---
+++ mysql-test/t/read_only_innodb.test 06/11/10 20:17:43
# should work with embedded server after mysqltest is fixed
-- source include/not_embedded.inc
-- source include/have_innodb.inc
#
# BUG#11733: COMMITs should not happen if read-only is set
#
--disable_warnings
DROP TABLE IF EXISTS table_11733 ;
--enable_warnings
# READ_ONLY does nothing to SUPER users
# so we use a non-SUPER one:
grant CREATE, SELECT, DROP on *.* to test@localhost;
connect (con1,localhost,test,,test);
connection default;
set global read_only=0;
# Any transactional engine will do
create table table_11733 (a int) engine=InnoDb;
connection con1;
BEGIN;
insert into table_11733 values(11733);
connection default;
set global read_only=1;
connection con1;
select @@global.read_only;
select * from table_11733 ;
-- error ER_OPTION_PREVENTS_STATEMENT
COMMIT;
connection default;
set global read_only=0;
drop table table_11733 ;
drop user test@localhost;
--- 1.200/sql/set_var.cc 2006-11-10 20:17:51 -07:00
+++ 1.201/sql/set_var.cc 2006-11-10 20:17:51 -07:00
@@ -370,7 +370,7 @@ sys_var_thd_ulong sys_preload_buff
&SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size);
-sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
+sys_var_opt_readonly sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
sys_var_thd_ulong sys_div_precincrement("div_precision_increment",
@@ -3879,6 +3879,36 @@ bool sys_var_trust_routine_creators::upd
warn_deprecated(thd);
return sys_var_bool_ptr::update(thd, var);
}
+
+
+bool sys_var_opt_readonly::update(THD *thd, set_var *var)
+{
+ bool result;
+
+ DBUG_ENTER("sys_var_opt_readonly::update");
+
+ /* Prevent self dead-lock */
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ DBUG_RETURN(true);
+ }
+
+ if (lock_global_read_lock(thd))
+ DBUG_RETURN(true);
+
+ if (result= make_global_read_lock_block_commit(thd))
+ goto end_with_read_lock;
+
+ /* Change the opt_readonly system variable, safe because the lock is held */
+ result= sys_var_bool_ptr::update(thd, var);
+
+end_with_read_lock:
+ /* Release the lock */
+ unlock_global_read_lock(thd);
+ DBUG_RETURN(result);
+}
+
/* even session variable here requires SUPER, because of -#o,file */
bool sys_var_thd_dbug::check(THD *thd, set_var *var)
--- 1.93/sql/set_var.h 2006-11-10 20:17:51 -07:00
+++ 1.94/sql/set_var.h 2006-11-10 20:17:51 -07:00
@@ -905,6 +905,20 @@ public:
};
+/**
+ Handler for setting the system variable --read-only.
+*/
+
+class sys_var_opt_readonly :public sys_var_bool_ptr
+{
+public:
+ sys_var_opt_readonly(const char *name_arg, my_bool *value_arg) :
+ sys_var_bool_ptr(name_arg, value_arg) {};
+ ~sys_var_opt_readonly() {};
+ bool update(THD *thd, set_var *var);
+};
+
+
class sys_var_thd_lc_time_names :public sys_var_thd
{
public:
| Thread |
|---|
| • bk commit into 5.1 tree (malff:1.2344) BUG#22009 | marc.alff | 11 Nov |