Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions mysql-test/suite/innodb_gis/r/rtree_search.result
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,39 @@ count(*)
drop procedure curdemo;
drop table t3;
drop table t1;
#
# MDEV 26123 : Always mark spatial index reads as locking
#
SET @old_autocommit = @@autocommit;
SET @old_tx_read_only = @@session.tx_read_only;
CREATE TABLE t1 (
c1 INT PRIMARY KEY,
category INT NOT NULL,
p POINT NOT NULL,
KEY idx_category (category),
SPATIAL INDEX sp_idx_p (p)
) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(1, 10, POINT(1,2));
CREATE PROCEDURE populate_t1()
BEGIN
DECLARE i INT DEFAULT 2;
WHILE i <= 5000 DO
INSERT INTO t1 VALUES
(i, 20, POINT(5,5));
SET i = i + 1;
END WHILE;
END |
CALL populate_t1();
SELECT COUNT(*) FROM t1 WHERE ST_Contains(t1.p, (SELECT p FROM t1 WHERE category = 10));
COUNT(*)
1
SET SESSION TRANSACTION READ ONLY;
SET autocommit = OFF;
SELECT COUNT(*) FROM t1 WHERE category = (SELECT category FROM t1 WHERE ST_EQUALS(p, POINT(1,2)));
COUNT(*)
1
SET autocommit = @old_autocommit;
SET SESSION tx_read_only = @old_tx_read_only;
DROP PROCEDURE populate_t1;
DROP TABLE t1;
42 changes: 42 additions & 0 deletions mysql-test/suite/innodb_gis/t/rtree_search.test
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,45 @@ drop procedure curdemo;
drop table t3;
drop table t1;

--echo #
--echo # MDEV 26123 : Always mark spatial index reads as locking
--echo #
SET @old_autocommit = @@autocommit;
SET @old_tx_read_only = @@session.tx_read_only;

CREATE TABLE t1 (
c1 INT PRIMARY KEY,
category INT NOT NULL,
p POINT NOT NULL,
KEY idx_category (category),
SPATIAL INDEX sp_idx_p (p)
) ENGINE=InnoDB;

INSERT INTO t1 VALUES
(1, 10, POINT(1,2));

DELIMITER |;
CREATE PROCEDURE populate_t1()
BEGIN
DECLARE i INT DEFAULT 2;

WHILE i <= 5000 DO
INSERT INTO t1 VALUES
(i, 20, POINT(5,5));
SET i = i + 1;
END WHILE;
END |
DELIMITER ;|
CALL populate_t1();

SELECT COUNT(*) FROM t1 WHERE ST_Contains(t1.p, (SELECT p FROM t1 WHERE category = 10));

SET SESSION TRANSACTION READ ONLY;
SET autocommit = OFF;
SELECT COUNT(*) FROM t1 WHERE category = (SELECT category FROM t1 WHERE ST_EQUALS(p, POINT(1,2)));

# Cleanup
SET autocommit = @old_autocommit;
SET SESSION tx_read_only = @old_tx_read_only;
DROP PROCEDURE populate_t1;
DROP TABLE t1;
8 changes: 2 additions & 6 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9012,12 +9012,8 @@ ha_innobase::index_read(

/* For R-Tree index, we will always place the page lock to
pages being searched */
if (index->is_spatial() && !m_prebuilt->trx->will_lock) {
if (trx_state != TRX_STATE_NOT_STARTED) {
DBUG_RETURN(HA_ERR_READ_ONLY_TRANSACTION);
} else {
m_prebuilt->trx->will_lock = true;
}
if (index->is_spatial()) {
m_prebuilt->trx->will_lock = true;
}
Comment on lines +9015 to 9017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the transaction is explicitly started as read-only (i.e., m_prebuilt->trx->read_only is true), setting will_lock = true and subsequently attempting to acquire predicate locks on the spatial index will lead to assertion failures (e.g., ut_ad(!trx->read_only) in lock_rec_lock_slow()) in debug builds, or undefined behavior/crashes in release builds.

We should check if m_prebuilt->trx->read_only is true and return HA_ERR_READ_ONLY_TRANSACTION in that case to safely prevent locking in read-only transactions.

	if (index->is_spatial()) {
		if (m_prebuilt->trx->read_only) {
			DBUG_RETURN(HA_ERR_READ_ONLY_TRANSACTION);
		}
		m_prebuilt->trx->will_lock = true;
	}

@mariadb-TafzeelShams mariadb-TafzeelShams Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below testcase works even without the patch.
Where trx->will_lock==true along with trx->read_only==true
Even though our transaction is explicitly set as read only, for spatial index we need to prevent parent path from other write transactions by acquiring locks.

SET SESSION TRANSACTION READ ONLY;
SELECT COUNT(*) FROM t1 WHERE category = (SELECT category FROM t1 WHERE ST_EQUALS(p, POINT(1,2)));


/* Note that if the index for which the search template is built is not
Expand Down