中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MYSQL對表的最大ID搶加鎖時的阻塞分析

發布時間:2021-09-10 15:25:11 來源:億速云 閱讀:351 作者:chen 欄目:MySQL數據庫

本篇內容介紹了“MYSQL對表的最大ID搶加鎖時的阻塞分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

示例SQL:

SELECT
	q.queueid
FROM
	render.queues q
WHERE
	q.queueid in (
		SELECT
			max(queueid)
		FROM
			(
				SELECT
					t.queueid
				FROM
					queues t
				WHERE
					1 = 1
				AND STATUS = 0
				AND queuetype <> 1
				。。。
				ORDER BY
					queuetype ASC,
					createdate ASC
			) a  limit 1
	)  FOR UPDATE ;

需求:

從ORACLE轉化到MYSQL的SQL,目的是多個會話輪詢取表中滿足條件最大ID的一行數據,然后第一個搶到的會話需要對這一行數據加鎖,以免其他會話讀到該行數據,在這期間,表是會不斷有新進數據插入的。

問題過程:

A會話執行 select for update;

queues 11:03:13>set autocommit=0
    -> ;
Query OK, 0 rows affected (0.00 sec)
    -> SELECT
    -> q.queueid
    -> FROM
    -> queues.queues q
    -> WHERE
    -> q.queueid IN (
    -> SELECT
    -> max(queueid)
    -> FROM
    -> (
    -> SELECT
    -> t.queueid
    -> FROM
    -> queues t
    -> WHERE
    -> 1 = 1
    -> AND STATUS = 0
    -> AND queuetype <> 1
    。。。
    -> ORDER BY
    -> queuetype ASC,
    -> createdate ASC
    -> ) a 
    -> ) FOR UPDATE ;
+-----------+
| queueid   |
+-----------+
| 278082656 |
+-----------+
1 row in set (24.46 sec)

此時 B 會話繼續往表中插入數據,讓ID不斷增長,例如當前滿足條件的最大 QUEUEID 是278082665

接著 C 會話重新執行以上 SELECT  for update語句,理論上,當再次查詢時需要加鎖的ID 應該是 278082665,但發現此時C會話在等待鎖。

分析:

于是,查了下鎖看看:

oot@(none) 01:52:24>select * from information_schema.INNODB_LOCKS\G;
*************************** 1. row ***************************
    lock_id: 133781546:45140:18:178
lock_trx_id: 133781546
  lock_mode: X
  lock_type: RECORD
 lock_table: `queues`.`queues`
 lock_index: INDEX_QUEUE_QUEUETYPE
 lock_space: 45140
  lock_page: 18
   lock_rec: 178
  lock_data: 0, 0, '1000505419', 0x99A438AAF5, 1280, 960, 278082656
*************************** 2. row ***************************
    lock_id: 133777540:45140:18:178
lock_trx_id: 133777540
  lock_mode: X
  lock_type: RECORD
 lock_table: `queues`.`queues`
 lock_index: INDEX_QUEUE_QUEUETYPE
 lock_space: 45140
  lock_page: 18
   lock_rec: 178
  lock_data: 0, 0, '1000505419', 0x99A438AAF5, 1280, 960, 278082656
2 rows in set, 1 warning (0.00 sec)
ERROR: 
No query specified
root@(none) 01:52:24>select * from information_schema.INNODB_LOCK_waits\G;
*************************** 1. row ***************************
requesting_trx_id: 133781546
requested_lock_id: 133781546:45140:18:178
  blocking_trx_id: 133777540
 blocking_lock_id: 133777540:45140:18:178
1 row in set, 1 warning (0.00 sec)

從上面結果發現lock_index是 INDEX_QUEUE_QUEUETYPE,而從SQL,我們繼續查看執行計劃 。

+----+-------------+-------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys         | key                   | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+
|  1 | PRIMARY     | q     | NULL       | index | NULL                  | INDEX_QUEUE_QUEUETYPE | 285     | NULL | 2067 |   100.00 | Using where; Using index |
|  2 | SUBQUERY    | t     | NULL       | ALL   | INDEX_QUEUE_QUEUETYPE | NULL                  | NULL    | NULL | 2067 |     0.05 | Using where              |
+----+-------------+-------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+

很明顯,主查詢使用了子查詢的索引,而該索引是非唯一性索引,MYSQL 的加鎖是基于索引加鎖的,同時從以上鎖情況可以看出此存在對包含278082656在內的多條數據進行加鎖。

怎么解決:

于是我們再重新看SQL,其實這里應該是要讓主查詢走具有唯一性的主鍵索引即可,這樣便不會存在以上問題了,只需將主查詢的WHERE q.queueid in ()改成 WHERE q.queueid =() ,這是開發規范問題。

SELECT
	q.queueid
FROM
	queues.queues q
WHERE
	q.queueid =(
		SELECT
			max(queueid)
		FROM
			(
				SELECT
					t.queueid
				FROM
					queues t
				WHERE
					1 = 1
				AND STATUS = 0
				AND queuetype <> 1
				。。。
				ORDER BY
					queuetype ASC,
					createdate ASC
			) a  limit 1
	)  FOR UPDATE

修改之后的執行計劃:

+----+-------------+-------+------------+-------+-----------------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys         | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+-----------------------+---------+---------+-------+------+----------+-------------+
|  1 | PRIMARY     | q     | NULL       | const | PRIMARY               | PRIMARY | 8       | const |    1 |   100.00 | Using index |
|  2 | SUBQUERY    | t     | NULL       | ALL   | INDEX_QUEUE_QUEUETYPE | NULL    | NULL    | NULL  | 2067 |     0.05 | Using where |
+----+-------------+-------+------------+-------+-----------------------+---------+---------+-------+------+----------+-------------+

“MYSQL對表的最大ID搶加鎖時的阻塞分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

前郭尔| 土默特右旗| 基隆市| 台江县| 保靖县| 始兴县| 铅山县| 姜堰市| 田林县| 贺兰县| 浮梁县| 罗平县| 闽清县| 丹江口市| 两当县| 蒙阴县| 迭部县| 漾濞| 漠河县| 德安县| 青浦区| 桦川县| 集贤县| 静安区| 怀安县| 广平县| 昆山市| 湟源县| 县级市| 夹江县| 南城县| 陵水| 桃源县| 泉州市| 武安市| 久治县| 淅川县| 手游| 汉寿县| 体育| 包头市|