Fix for bug #28837: MyISAM storage engine error (134) doing delete with
self-join When doing DELETE with self-join on a MyISAM or MERGE table, it could happen that a record being retrieved in join_read_next_same() has already been deleted by previous iterations. That caused the engine's index_next_same() method to fail with HA_ERR_RECORD_DELETED error and the whole DELETE query to be aborted with an error. Fixed by suppressing the HA_ERR_RECORD_DELETED error in hy_myisam::index_next_same() and ha_myisammrg::index_next_same(). Since HA_ERR_RECORD_DELETED can only be returned by MyISAM, there is no point in filtering this error in the SQL layer. mysql-test/r/merge.result: Added a test case for bug #28837. mysql-test/r/myisam.result: Added a test case for bug #28837. mysql-test/t/merge.test: Added a test case for bug #28837. mysql-test/t/myisam.test: Added a test case for bug #28837. sql/ha_myisam.cc: Skip HA_ERR_RECORD_DELETED silently when calling mi_rnext_same(). sql/ha_myisammrg.cc: Skip HA_ERR_RECORD_DELETED silently when calling mi_rnext_same().
This commit is contained in:
parent
1c1dd1f25c
commit
67bf39f241
@ -876,4 +876,41 @@ CHECK TABLE tm1;
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.tm1 check status OK
|
test.tm1 check status OK
|
||||||
DROP TABLE tm1, t1, t2;
|
DROP TABLE tm1, t1, t2;
|
||||||
|
CREATE TABLE t1 (id INT NOT NULL, ref INT NOT NULL, INDEX (id)) ENGINE=MyISAM;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
CREATE TABLE t3 (id INT NOT NULL, ref INT NOT NULL, INDEX (id)) ENGINE=MERGE
|
||||||
|
UNION(t1);
|
||||||
|
SELECT * FROM t3 AS a INNER JOIN t3 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
id ref ref
|
||||||
|
4 4 5
|
||||||
|
4 4 5
|
||||||
|
4 4 5
|
||||||
|
4 4 5
|
||||||
|
SELECT * FROM t3;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
4 4
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
4 4
|
||||||
|
DELETE FROM a USING t3 AS a INNER JOIN t3 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t3;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -1806,4 +1806,26 @@ SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
|||||||
a
|
a
|
||||||
1
|
1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id)) ENGINE=MyISAM;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
id ref ref
|
||||||
|
4 4 5
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
4 4
|
||||||
|
DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
DROP TABLE t1, t2;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -507,4 +507,26 @@ SELECT * FROM tm1;
|
|||||||
CHECK TABLE tm1;
|
CHECK TABLE tm1;
|
||||||
DROP TABLE tm1, t1, t2;
|
DROP TABLE tm1, t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #28837: MyISAM storage engine error (134) doing delete with self-join
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id INT NOT NULL, ref INT NOT NULL, INDEX (id)) ENGINE=MyISAM;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
|
||||||
|
CREATE TABLE t3 (id INT NOT NULL, ref INT NOT NULL, INDEX (id)) ENGINE=MERGE
|
||||||
|
UNION(t1);
|
||||||
|
|
||||||
|
SELECT * FROM t3 AS a INNER JOIN t3 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t3;
|
||||||
|
DELETE FROM a USING t3 AS a INNER JOIN t3 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t3;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
@ -1161,4 +1161,21 @@ ALTER TABLE t1 ENABLE KEYS;
|
|||||||
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28837: MyISAM storage engine error (134) doing delete with self-join
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id)) ENGINE=MyISAM;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
|
||||||
|
SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
@ -1602,10 +1602,14 @@ int ha_myisam::index_next_same(byte * buf,
|
|||||||
const byte *key __attribute__((unused)),
|
const byte *key __attribute__((unused)),
|
||||||
uint length __attribute__((unused)))
|
uint length __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
DBUG_ASSERT(inited==INDEX);
|
DBUG_ASSERT(inited==INDEX);
|
||||||
statistic_increment(table->in_use->status_var.ha_read_next_count,
|
statistic_increment(table->in_use->status_var.ha_read_next_count,
|
||||||
&LOCK_status);
|
&LOCK_status);
|
||||||
int error=mi_rnext_same(file,buf);
|
do
|
||||||
|
{
|
||||||
|
error= mi_rnext_same(file,buf);
|
||||||
|
} while (error == HA_ERR_RECORD_DELETED);
|
||||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -294,9 +294,13 @@ int ha_myisammrg::index_next_same(byte * buf,
|
|||||||
const byte *key __attribute__((unused)),
|
const byte *key __attribute__((unused)),
|
||||||
uint length __attribute__((unused)))
|
uint length __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
statistic_increment(table->in_use->status_var.ha_read_next_count,
|
statistic_increment(table->in_use->status_var.ha_read_next_count,
|
||||||
&LOCK_status);
|
&LOCK_status);
|
||||||
int error=myrg_rnext_same(file,buf);
|
do
|
||||||
|
{
|
||||||
|
error= myrg_rnext_same(file,buf);
|
||||||
|
} while (error == HA_ERR_RECORD_DELETED);
|
||||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user