mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-24607 Atomic CREATE VIEW
The logic of the new code is: - Log CREATE view to DDL log, with a marker if old view existed - If old view exists (in case of CREATE or REPLACE view), make a copy of the old view as view_name.frm- - Create the new view definition file - Delete copy of view if it was created. Crash recovery: - Delete view_name.frm~ file (Temporary file for view definition) - If query was logged to binary log - Delete copy of view if it exists - else -rename the copy of the view over the .frm file (restoring the old definition) One benefit of the new code is that CREATE OR REPLACE VIEW for an existing view is no fully atomic: Either the view will be replaced or the old one will be left unchanged.
This commit is contained in:
82
mysql-test/suite/atomic/create_view.result
Normal file
82
mysql-test/suite/atomic/create_view.result
Normal file
@ -0,0 +1,82 @@
|
||||
query: CREATE VIEW t1 as select "new"
|
||||
crash point: ddl_log_create_before_copy_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: definition_file_after_create
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_binlog
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_binlog
|
||||
t1.frm
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
master-bin.000001 # Query # # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t1` AS select "new"
|
||||
query: CREATE OR REPLACE VIEW t1 as select "new"
|
||||
crash point: ddl_log_create_before_copy_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: definition_file_after_create
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_binlog
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_binlog
|
||||
t1.frm
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
master-bin.000001 # Query # # use `test`; CREATE OR REPLACE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t1` AS select "new"
|
||||
query: CREATE OR REPLACE VIEW t2 as select "new"
|
||||
crash point: ddl_log_create_before_copy_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: definition_file_after_create
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_create_view
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_before_binlog
|
||||
t2.frm
|
||||
old
|
||||
old
|
||||
crash point: ddl_log_create_after_binlog
|
||||
t2.frm
|
||||
new
|
||||
new
|
||||
master-bin.000001 # Query # # use `test`; CREATE OR REPLACE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t2` AS select "new"
|
||||
Warnings:
|
||||
Note 4092 Unknown VIEW: 'test.t1,test.t2'
|
88
mysql-test/suite/atomic/create_view.test
Normal file
88
mysql-test/suite/atomic/create_view.test
Normal file
@ -0,0 +1,88 @@
|
||||
--source include/have_debug.inc
|
||||
--source include/have_sequence.inc
|
||||
--source include/have_log_bin.inc
|
||||
--source include/not_valgrind.inc
|
||||
|
||||
#
|
||||
# Testing of atomic create view with crashes in a lot of different places
|
||||
|
||||
--disable_query_log
|
||||
call mtr.add_suppression("InnoDB: .* does not exist in the InnoDB internal");
|
||||
--enable_query_log
|
||||
let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
||||
|
||||
let $crash_count=6;
|
||||
let $crash_points='ddl_log_create_before_copy_view', 'ddl_log_create_before_create_view', 'definition_file_after_create','ddl_log_create_after_create_view', 'ddl_log_create_before_binlog', 'ddl_log_create_after_binlog';
|
||||
|
||||
let $statement_count=3;
|
||||
let $statements='CREATE VIEW t1 as select "new"',
|
||||
'CREATE OR REPLACE VIEW t1 as select "new"',
|
||||
'CREATE OR REPLACE VIEW t2 as select "new"';
|
||||
|
||||
let $old_debug=`select @@debug_dbug`;
|
||||
|
||||
let $e=0;
|
||||
let $keep_include_silent=1;
|
||||
let $grep_script=CREATE|DROP;
|
||||
--disable_query_log
|
||||
|
||||
while ($e < 1)
|
||||
{
|
||||
inc $e;
|
||||
|
||||
let $r=0;
|
||||
while ($r < $statement_count)
|
||||
{
|
||||
inc $r;
|
||||
|
||||
let $statement=`select ELT($r, $statements)`;
|
||||
--echo query: $statement
|
||||
|
||||
let $c=0;
|
||||
while ($c < $crash_count)
|
||||
{
|
||||
inc $c;
|
||||
let $crash=`select ELT($c, $crash_points)`;
|
||||
|
||||
create view t2 as select "old";
|
||||
|
||||
RESET MASTER;
|
||||
--echo crash point: $crash
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--disable_reconnect
|
||||
--eval set @@debug_dbug="+d,$crash",@debug_crash_counter=1
|
||||
let $errno=0;
|
||||
--error 0,2013
|
||||
--eval $statement;
|
||||
let $error=$errno;
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
--disable_query_log
|
||||
--eval set @@debug_dbug="$old_debug"
|
||||
|
||||
if ($error == 0)
|
||||
{
|
||||
echo "No crash!";
|
||||
}
|
||||
# Check which tables still exists
|
||||
--list_files $MYSQLD_DATADIR/test t*
|
||||
--list_files $MYSQLD_DATADIR/test *sql*
|
||||
select * from t2;
|
||||
|
||||
--let $binlog_file=master-bin.000001
|
||||
--source include/show_binlog_events.inc
|
||||
if ($error)
|
||||
{
|
||||
--let $binlog_file=master-bin.000002
|
||||
--source include/show_binlog_events.inc
|
||||
}
|
||||
# Drop the tables. The warnings will show what was dropped
|
||||
--disable_warnings
|
||||
drop view if exists t1,t2;
|
||||
--enable_warnings
|
||||
}
|
||||
}
|
||||
}
|
||||
drop view if exists t1,t2;
|
||||
|
||||
--enable_query_log
|
Reference in New Issue
Block a user