Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
d7263d2a
Commit
d7263d2a
authored
Oct 21, 2008
by
Davi Arnaut
Browse files
Options
Browse Files
Download
Plain Diff
Merge Bug#28323 to mysql-5.1.29-rc
parents
0c20c0f1
41dd7b6b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
147 additions
and
11 deletions
+147
-11
mysql-test/r/xa.result
mysql-test/r/xa.result
+19
-0
mysql-test/t/xa.test
mysql-test/t/xa.test
+44
-0
sql/handler.cc
sql/handler.cc
+6
-1
sql/share/errmsg.txt
sql/share/errmsg.txt
+6
-0
sql/sql_class.h
sql/sql_class.h
+3
-1
sql/sql_parse.cc
sql/sql_parse.cc
+69
-9
No files found.
mysql-test/r/xa.result
View file @
d7263d2a
...
...
@@ -55,3 +55,22 @@ select * from t1;
a
20
drop table t1;
drop table if exists t1;
create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb;
insert into t1 values(1, 1, 'a');
insert into t1 values(2, 2, 'b');
xa start 'a','b';
update t1 set c = 'aa' where a = 1;
xa start 'a','c';
update t1 set c = 'bb' where a = 2;
update t1 set c = 'bb' where a = 2;
update t1 set c = 'aa' where a = 1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
select count(*) from t1;
count(*)
2
xa end 'a','c';
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
xa rollback 'a','c';
xa start 'a','c';
End of 5.0 tests
mysql-test/t/xa.test
View file @
d7263d2a
...
...
@@ -74,3 +74,47 @@ xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
select
*
from
t1
;
drop
table
t1
;
disconnect
con1
;
#
# Bug#28323: Server crashed in xid cache operations
#
--
disable_warnings
drop
table
if
exists
t1
;
--
enable_warnings
create
table
t1
(
a
int
,
b
int
,
c
varchar
(
20
),
primary
key
(
a
))
engine
=
innodb
;
insert
into
t1
values
(
1
,
1
,
'a'
);
insert
into
t1
values
(
2
,
2
,
'b'
);
connect
(
con1
,
localhost
,
root
,,);
connect
(
con2
,
localhost
,
root
,,);
--
connection
con1
xa
start
'a'
,
'b'
;
update
t1
set
c
=
'aa'
where
a
=
1
;
--
connection
con2
xa
start
'a'
,
'c'
;
update
t1
set
c
=
'bb'
where
a
=
2
;
--
connection
con1
--
send
update
t1
set
c
=
'bb'
where
a
=
2
--
connection
con2
--
sleep
1
--
error
ER_LOCK_DEADLOCK
update
t1
set
c
=
'aa'
where
a
=
1
;
select
count
(
*
)
from
t1
;
--
error
ER_XA_RBDEADLOCK
xa
end
'a'
,
'c'
;
xa
rollback
'a'
,
'c'
;
--
disconnect
con2
connect
(
con3
,
localhost
,
root
,,);
--
connection
con3
xa
start
'a'
,
'c'
;
--
disconnect
con1
--
disconnect
con3
--
connection
default
--
echo
End
of
5.0
tests
sql/handler.cc
View file @
d7263d2a
...
...
@@ -1278,7 +1278,12 @@ int ha_rollback_trans(THD *thd, bool all)
trans
->
ha_list
=
0
;
trans
->
no_2pc
=
0
;
if
(
is_real_trans
)
thd
->
transaction
.
xid_state
.
xid
.
null
();
{
if
(
thd
->
transaction_rollback_request
)
thd
->
transaction
.
xid_state
.
rm_error
=
thd
->
main_da
.
sql_errno
();
else
thd
->
transaction
.
xid_state
.
xid
.
null
();
}
if
(
all
)
{
thd
->
variables
.
tx_isolation
=
thd
->
session_tx_isolation
;
...
...
sql/share/errmsg.txt
View file @
d7263d2a
...
...
@@ -6128,6 +6128,12 @@ ER_LOAD_DATA_INVALID_COLUMN
ER_LOG_PURGE_NO_FILE
eng "Being purged log %s was not found"
ER_XA_RBTIMEOUT XA106
eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long"
ER_XA_RBDEADLOCK XA102
eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected"
ER_NEED_REPREPARE
eng "Prepared statement needs to be re-prepared"
...
...
sql/sql_class.h
View file @
d7263d2a
...
...
@@ -739,7 +739,7 @@ struct st_savepoint {
Ha_trx_info
*
ha_list
;
};
enum
xa_states
{
XA_NOTR
=
0
,
XA_ACTIVE
,
XA_IDLE
,
XA_PREPARED
};
enum
xa_states
{
XA_NOTR
=
0
,
XA_ACTIVE
,
XA_IDLE
,
XA_PREPARED
,
XA_ROLLBACK_ONLY
};
extern
const
char
*
xa_state_names
[];
typedef
struct
st_xid_state
{
...
...
@@ -747,6 +747,8 @@ typedef struct st_xid_state {
XID
xid
;
// transaction identifier
enum
xa_states
xa_state
;
// used by external XA only
bool
in_thd
;
/* Error reported by the Resource Manager (RM) to the Transaction Manager. */
uint
rm_error
;
}
XID_STATE
;
extern
pthread_mutex_t
LOCK_xid_cache
;
...
...
sql/sql_parse.cc
View file @
d7263d2a
...
...
@@ -83,9 +83,57 @@ const LEX_STRING command_name[]={
};
const
char
*
xa_state_names
[]
=
{
"NON-EXISTING"
,
"ACTIVE"
,
"IDLE"
,
"PREPARED"
"NON-EXISTING"
,
"ACTIVE"
,
"IDLE"
,
"PREPARED"
,
"ROLLBACK ONLY"
};
/**
Mark a XA transaction as rollback-only if the RM unilaterally
rolled back the transaction branch.
@note If a rollback was requested by the RM, this function sets
the appropriate rollback error code and transits the state
to XA_ROLLBACK_ONLY.
@return TRUE if transaction was rolled back or if the transaction
state is XA_ROLLBACK_ONLY. FALSE otherwise.
*/
static
bool
xa_trans_rolled_back
(
XID_STATE
*
xid_state
)
{
if
(
xid_state
->
rm_error
)
{
switch
(
xid_state
->
rm_error
)
{
case
ER_LOCK_WAIT_TIMEOUT
:
my_error
(
ER_XA_RBTIMEOUT
,
MYF
(
0
));
break
;
case
ER_LOCK_DEADLOCK
:
my_error
(
ER_XA_RBDEADLOCK
,
MYF
(
0
));
break
;
default:
my_error
(
ER_XA_RBROLLBACK
,
MYF
(
0
));
}
xid_state
->
xa_state
=
XA_ROLLBACK_ONLY
;
}
return
(
xid_state
->
xa_state
==
XA_ROLLBACK_ONLY
);
}
/**
Rollback work done on behalf of at ransaction branch.
*/
static
bool
xa_trans_rollback
(
THD
*
thd
)
{
bool
status
=
test
(
ha_rollback
(
thd
));
thd
->
options
&=
~
(
ulong
)
OPTION_BEGIN
;
thd
->
transaction
.
all
.
modified_non_trans_table
=
FALSE
;
thd
->
server_status
&=
~
SERVER_STATUS_IN_TRANS
;
xid_cache_delete
(
&
thd
->
transaction
.
xid_state
);
thd
->
transaction
.
xid_state
.
xa_state
=
XA_NOTR
;
thd
->
transaction
.
xid_state
.
rm_error
=
0
;
return
status
;
}
static
void
unlock_locked_tables
(
THD
*
thd
)
{
if
(
thd
->
locked_tables
)
...
...
@@ -4505,6 +4553,7 @@ create_sp_error:
}
DBUG_ASSERT
(
thd
->
transaction
.
xid_state
.
xid
.
is_null
());
thd
->
transaction
.
xid_state
.
xa_state
=
XA_ACTIVE
;
thd
->
transaction
.
xid_state
.
rm_error
=
0
;
thd
->
transaction
.
xid_state
.
xid
.
set
(
thd
->
lex
->
xid
);
xid_cache_insert
(
&
thd
->
transaction
.
xid_state
);
thd
->
transaction
.
all
.
modified_non_trans_table
=
FALSE
;
...
...
@@ -4530,6 +4579,8 @@ create_sp_error:
my_error
(
ER_XAER_NOTA
,
MYF
(
0
));
break
;
}
if
(
xa_trans_rolled_back
(
&
thd
->
transaction
.
xid_state
))
break
;
thd
->
transaction
.
xid_state
.
xa_state
=
XA_IDLE
;
my_ok
(
thd
);
break
;
...
...
@@ -4561,6 +4612,12 @@ create_sp_error:
XID_STATE
*
xs
=
xid_cache_search
(
thd
->
lex
->
xid
);
if
(
!
xs
||
xs
->
in_thd
)
my_error
(
ER_XAER_NOTA
,
MYF
(
0
));
else
if
(
xa_trans_rolled_back
(
xs
))
{
ha_commit_or_rollback_by_xid
(
thd
->
lex
->
xid
,
0
);
xid_cache_delete
(
xs
);
break
;
}
else
{
ha_commit_or_rollback_by_xid
(
thd
->
lex
->
xid
,
1
);
...
...
@@ -4569,6 +4626,11 @@ create_sp_error:
}
break
;
}
if
(
xa_trans_rolled_back
(
&
thd
->
transaction
.
xid_state
))
{
xa_trans_rollback
(
thd
);
break
;
}
if
(
thd
->
transaction
.
xid_state
.
xa_state
==
XA_IDLE
&&
thd
->
lex
->
xa_opt
==
XA_ONE_PHASE
)
{
...
...
@@ -4615,28 +4677,26 @@ create_sp_error:
my_error
(
ER_XAER_NOTA
,
MYF
(
0
));
else
{
bool
ok
=
!
xa_trans_rolled_back
(
xs
);
ha_commit_or_rollback_by_xid
(
thd
->
lex
->
xid
,
0
);
xid_cache_delete
(
xs
);
my_ok
(
thd
);
if
(
ok
)
my_ok
(
thd
);
}
break
;
}
if
(
thd
->
transaction
.
xid_state
.
xa_state
!=
XA_IDLE
&&
thd
->
transaction
.
xid_state
.
xa_state
!=
XA_PREPARED
)
thd
->
transaction
.
xid_state
.
xa_state
!=
XA_PREPARED
&&
thd
->
transaction
.
xid_state
.
xa_state
!=
XA_ROLLBACK_ONLY
)
{
my_error
(
ER_XAER_RMFAIL
,
MYF
(
0
),
xa_state_names
[
thd
->
transaction
.
xid_state
.
xa_state
]);
break
;
}
if
(
ha
_rollback
(
thd
))
if
(
xa_trans
_rollback
(
thd
))
my_error
(
ER_XAER_RMERR
,
MYF
(
0
));
else
my_ok
(
thd
);
thd
->
options
&=
~
(
OPTION_BEGIN
|
OPTION_KEEP_LOG
);
thd
->
transaction
.
all
.
modified_non_trans_table
=
FALSE
;
thd
->
server_status
&=
~
SERVER_STATUS_IN_TRANS
;
xid_cache_delete
(
&
thd
->
transaction
.
xid_state
);
thd
->
transaction
.
xid_state
.
xa_state
=
XA_NOTR
;
break
;
case
SQLCOM_XA_RECOVER
:
res
=
mysql_xa_recover
(
thd
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment