首页 > 数据库 >MySQL事务学习-2024-11-30

MySQL事务学习-2024-11-30

时间:2024-11-30 22:58:57浏览次数:10  
标签:11 IX 事务 -- lock 30 2024 article id

[学习记录]MySQL事务

锁的兼容情况总结-GPT

S锁和X锁的兼容性

在MySQL中,S锁(共享锁)和X锁(排他锁) 的兼容性如下:

锁类型S锁X锁
S锁√ 兼容× 不兼容
X锁× 不兼容× 不兼容

具体说明:

  • S锁(共享锁):

    • 多个事务可以同时对同一数据加S锁(即允许多个事务同时读取数据)。
    • 如果一个事务已经持有S锁,其他事务无法对该数据加X锁。
  • X锁(排他锁):

    • 持有X锁的事务可以读写数据。
    • 如果一个事务已经持有X锁,其他事务无法对该数据加S锁或X锁。

IS和IX的机制

IS锁(意向共享锁)和IX锁(意向排他锁)表级锁,用于协调行级锁的加锁意图。

目的:
  • 避免表级锁与行级锁冲突时的重复检查。

  • 提高事务处理的效率。

锁类型与兼容性

注意, 这里的内容,我去找了官网的说明, 以避免GPT结果不正确, 官网地址: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
以下是 MySQL8.0 官网上的表级锁类型兼容性总结
Compatible: 兼容的
Conflict: 冲突
MySQL8.0 官网上的表级锁类型兼容性总结
从这里开始下面的还是GPT的总结

IS锁(意向共享锁)
  • 特点:
    • 表示事务想要在某些行上加S锁。
    • 兼容其他事务的IS锁和IX锁。
    • 与S锁和X锁的兼容性根据表锁情况判断。
  • 场景:
    当事务对表中某些行加S锁时,事务会先在表上申请IS锁。
IX锁(意向排他锁)
  • 特点:
    • 表示事务想要在某些行上加X锁。
    • 兼容其他事务的IS锁和IX锁。
    • 不兼容S锁或X锁。
  • 场景:
    • 当事务对表中某些行加X锁时,事务会先在表上申请IX锁。

S锁、X锁与IS、IX锁的关系

  1. 行级锁操作的前置步骤:

    • 如果事务要对行加S锁,必须先在表级别加IS锁。

    • 如果事务要对行加X锁,必须先在表级别加IX锁。

  2. 加锁顺序:

    • 表级意向锁(IS或IX)与行级锁(S或X)配合使用。

    • 例如,事务对表的一行记录加S锁时,会先对表加IS锁。

总结

  • S锁和X锁可用于行级的数据保护,控制数据的读写权限。
  • IS锁和IX锁是表级的意向锁,用于快速判断是否允许对某些行加行级锁。
  • 锁兼容性:
    • S锁适用于多事务同时读,但与X锁冲突。
    • IX锁和IS锁之间兼容,但意向锁与表级S锁或X锁可能冲突。

官网中关于Intention Locks(意向)的说明

There are two types of intention locks:
有两种类型的意图锁:

  • An intention shared lock (IS) indicates that a transaction intends to set a shared lock on individual rows in a table.
  • 意图共享锁(IS) 表示一个事务打算对表中的某些行设置共享锁。
  • An intention exclusive lock (IX) indicates that a transaction intends to set an exclusive lock on individual rows in a table.
  • 意图排他锁(IX) 表示一个事务打算对表中的某些行设置排他锁。

Intention locks do not block anything except full table requests (for example, LOCK TABLES … WRITE).

意图锁不会阻塞任何操作, 除非是对整个表的请求(例如,LOCK TABLES … WRITE)。

The main purpose of intention locks is to show that someone is locking a row, or going to lock a row in the table.
意图锁的主要目的是表明某个事务正在锁定某一行,或者即将锁定表中的某一行。


学习目标

  • 补充遗漏的最后一种: 共享锁与共享锁兼容.
  • 验证看看: IS锁与X锁的冲突, 是指明了X是表级锁的时候, 而不是行X锁.

SQL代码块记录

1. 共享锁与共享锁兼容

代码块
-- 1. 事务A针对id'3'上S锁
mysql> BEGIN;SELECT * FROM article WHERE id="3" LOCK IN SHARE MODE;
Query OK, 0 rows affected (0.00 sec)

+----+-------+-----------+--------------+
| id | name  | words_num | content_desc |
+----+-------+-----------+--------------+
| 3  | test2 |       999 | 1            |
+----+-------+-----------+--------------+
1 row in set (0.01 sec)

-- 2. 事务B针对id'3'上S锁
mysql> BEGIN;SELECT * FROM article WHERE id="3" LOCK IN SHARE MODE;
Query OK, 0 rows affected (0.00 sec)

+----+-------+-----------+--------------+
| id | name  | words_num | content_desc |
+----+-------+-----------+--------------+
| 3  | test2 |       999 | 1            |
+----+-------+-----------+--------------+
1 row in set (0.01 sec)

-- 3. 事务C针对id'3'上X锁
mysql> BEGIN;SELECT * FROM article WHERE id="3" for UPDATE;
Query OK, 0 rows affected (0.00 sec)
-- (会卡住)
-- 4. 在事务C超时前, 查看锁和事务的状态
mysql> select trx_id,trx_isolation_level from INNODB_TRX;
+-----------------+---------------------+
| trx_id          | trx_isolation_level |
+-----------------+---------------------+
|           15486 | REPEATABLE READ     |
| 284151884094088 | REPEATABLE READ     |
| 284151884093312 | REPEATABLE READ     |
+-----------------+---------------------+
3 rows in set (0.02 sec)

mysql> SELECT engine_lock_id, lock_type, lock_mode, lock_status, lock_data FROM performance_schema.data_locks;
+-------------------------------------+-----------+---------------+-------------+-----------+
| engine_lock_id                      | lock_type | lock_mode     | lock_status | lock_data |
+-------------------------------------+-----------+---------------+-------------+-----------+
| 2676907384208:1073:2676913017368    | TABLE     | IX            | GRANTED     | NULL      |
| 2676907384208:11:4:15:2676896897048 | RECORD    | X,REC_NOT_GAP | WAITING     | '3'       |
| 2676907382656:1073:2676913015832    | TABLE     | IS            | GRANTED     | NULL      |
| 2676907382656:11:4:15:2676896890904 | RECORD    | S,REC_NOT_GAP | GRANTED     | '3'       |
| 2676907383432:1073:2676913016600    | TABLE     | IS            | GRANTED     | NULL      |
| 2676907383432:11:4:15:2676896893976 | RECORD    | S,REC_NOT_GAP | GRANTED     | '3'       |
+-------------------------------------+-----------+---------------+-------------+-----------+
6 rows in set (0.03 sec)
-- 5. 在事务C超时前, 提交事务A和事务B, 然后就能看到事务C查出了结果(没什么特别的) 最后再看看锁和事务的状态做个结尾
-- 提交A
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
-- 提交B
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
-- 看到C
+----+-------+-----------+--------------+
| id | name  | words_num | content_desc |
+----+-------+-----------+--------------+
| 3  | test2 |       999 | 1            |
+----+-------+-----------+--------------+
1 row in set (4.17 sec)
-- 看看锁
mysql> SELECT engine_lock_id, lock_type, lock_mode, lock_status, lock_data FROM performance_schema.data_locks;
+-------------------------------------+-----------+---------------+-------------+-----------+
| engine_lock_id                      | lock_type | lock_mode     | lock_status | lock_data |
+-------------------------------------+-----------+---------------+-------------+-----------+
| 2676907384208:1073:2676913017368    | TABLE     | IX            | GRANTED     | NULL      |
| 2676907384208:11:4:15:2676896897048 | RECORD    | X,REC_NOT_GAP | GRANTED     | '3'       |
+-------------------------------------+-----------+---------------+-------------+-----------+
2 rows in set (0.03 sec)

执行结果
  • 很明显, 事务A的S锁,可以和事务B的S锁, 同时存在, 但是事务C的X锁, 需要等前面的S锁都释放了, 它才能拿到.
  • 不要忘记了, 这些都是在隔离等级是REPEATABLE READ时, 使用主键id进行: 行锁 的情况

2. IS锁与X锁的冲突, 是表级别的而不是行级别的. 但是IS锁与表级的S锁不冲突. IX锁与表级的S锁和X锁都冲突.

-- 重复过很多次了的就省略了. 下面仅作文字描述
-- 开启一个事务A,里面是select加S锁,锁定id='3'一行. 开启一个事务B, 里面是upadte, 改的是id='5'一行. 都操作的是表article
-- 查看当前锁的情况
mysql> SELECT engine_lock_id, lock_type, lock_mode, lock_status, lock_data FROM performance_schema.data_locks;
+-------------------------------------+-----------+---------------+-------------+-----------+
| engine_lock_id                      | lock_type | lock_mode     | lock_status | lock_data |
+-------------------------------------+-----------+---------------+-------------+-----------+
| 2676907382656:1073:2676913015832    | TABLE     | IX            | GRANTED     | NULL      |
| 2676907382656:11:4:14:2676896890904 | RECORD    | X,REC_NOT_GAP | GRANTED     | '5'       |
| 2676907383432:1073:2676913016600    | TABLE     | IS            | GRANTED     | NULL      |
| 2676907383432:11:4:15:2676896893976 | RECORD    | S,REC_NOT_GAP | GRANTED     | '3'       |
+-------------------------------------+-----------+---------------+-------------+-----------+
4 rows in set (0.03 sec)

-- 再开一个窗口, 尝试对article表,上S锁
mysql> Lock TABLES article READ;
-- (卡住了)

-- 换一个命令,看看表上的锁
mysql> SELECT * FROM performance_schema.metadata_locks where object_name='article';
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA   | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE        | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | be_able_to_read | article     | NULL        |         2676862518896 | SHARED_READ      | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             226 |             65 |
| TABLE       | be_able_to_read | article     | NULL        |         2676862521056 | SHARED_WRITE     | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             230 |             16 |
| TABLE       | be_able_to_read | article     | NULL        |         2676867725872 | SHARED_READ_ONLY | TRANSACTION   | PENDING     | sql_parse.cc:6140 |             229 |              6 |
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
3 rows in set (0.04 sec)

-- 去提交事务B
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
-- (此时能立刻看到, 旁边执行Lock TABLES article READ;窗口中的pedding消失了)

-- 查看表上的锁
mysql> SELECT * FROM performance_schema.metadata_locks where object_name='article';
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA   | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE        | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | be_able_to_read | article     | NULL        |         2676862518896 | SHARED_READ      | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             226 |             65 |
| TABLE       | be_able_to_read | article     | NULL        |         2676867725872 | SHARED_READ_ONLY | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             229 |              6 |
+-------------+-----------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
2 rows in set (0.04 sec)

-- 解除article表的S锁
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
-- 查看表上的锁
mysql> SELECT * FROM performance_schema.metadata_locks where object_name='article';
+-------------+-----------------+-------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA   | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE   | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+-----------------+-------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | be_able_to_read | article     | NULL        |         2676862518896 | SHARED_READ | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             226 |             65 |
+-------------+-----------------+-------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
1 row in set (0.04 sec)

-- 对article表上X锁
mysql> Lock TABLES article WRITE;
-- (卡住了)

-- 去提交事务A
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
-- (此时能立刻看到, 旁边执行Lock TABLES article WRITE;窗口中的pedding消失了)

-- 再看看表上的锁
mysql> SELECT * FROM performance_schema.metadata_locks where object_name='article';
+-------------+-----------------+-------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA   | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE            | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+-----------------+-------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | be_able_to_read | article     | NULL        |         2676867727216 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | sql_parse.cc:6140 |             229 |             11 |
+-------------+-----------------+-------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
1 row in set (0.04 sec)

现象

  1. 事务A给表上了IS锁, 事务B给表上了IX锁. 当IX锁存在时, 无法对表上READ的LOCK
  2. 释放了事务B的IX锁后, 事务A还占用IS锁时, 对表上READ的LOCK成功了
  3. 释放了事务B的IX锁后, 事务A还占用IS锁时, 对表上WRITE的LOCK会卡住
  4. 释放了事务A的IS锁后, 对表上WRITE的成功了
  5. IS锁可以和行X锁共存, IX锁也可以和行S锁,行X锁共存.

标签:11,IX,事务,--,lock,30,2024,article,id
From: https://blog.csdn.net/qq_21410843/article/details/144160038

相关文章

  • 20222306 2024-2025-1《网络与系统攻防技术》实验七实验报告
    1.实验内容1.1实验目的及要求本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法。具体实践有(1)简单应用SET工具建立冒名网站(2)ettercapDNSspoof(3)结合应用两种技术,用DNSspoof引导特定访问到冒名网站。1.2本周学习内容本周学习内容主要是Web安全,了解......
  • 2024.11.30 周六
    2024.11.30周六Q1.1200给定x(<=107),m(<=1018),循环i:1~m,t=i^x,问t为x或m因子的数量。Q2.1400给定n个数,选择四个坐标点组成一个边平行于坐标轴的矩形,问面积最大时选的点。Q3.1600给定一数组(非负),在非零数中每次可选一个数(代价本身)/相邻2个数(代价和的2倍)。问最小......
  • NOIP 2024 游记
    希望能撑过去。Day-1NOIP模拟赛终结篇。打的挺唐,挂了小100pts。rp++。下午正常体育课(出发前一天标配),打了篮球,手感逐渐变优。想到可能是HZOI2023最后一次这样打了,有点伤心。改题,调整心态,写题解,看板子。平凡的下午。晚饭后狂打板子不止,和Abnormal123看口胡之前的模拟......
  • 中睿智能:领航前行,2024智能仓储物流行业解决方案合作论坛盛启
    11月28日,由东莞市工业和信息化局指导,广东中睿智能科技有限公司(以下简称“中睿智能仓储”)主办的“仓储新动能智造新未来——2024智能仓储物流行业解决方案合作论坛”在东莞东城新发兴创新工场盛大举行。此次论坛汇聚了来自智能仓储物流行业的专家学者、企业精英和技术骨干,共......
  • P11218 【MX-S4-T2】「yyOI R2」youyou 不喜欢夏天
    ProblemSolve先不看yy,我们能够发现这个youyou可以贪心,即:某一列全是1,全选,有一个1,尽量只选1(因为可能和上一列的选择连不起来,要衔接),全0,尽量不要选再回来看yy,通过题意以及样例等数据来看,我们能够发现这个yy肯定只会对满足这样的列进行操作:上下两行只选了一行1,另一行是0通过......
  • NOIP2024 游记
    开题,先看A的特殊性质,然后很快就有了正解思路。写加调,还好这个机子安装了单步调试,很快就调完了但还是错,有点慌。5分钟瞪出两个错误,然后9:11过T1,2分钟检查,希望别挂。开T2,刚开始以为是推性质DP题,后来发现直接乘法原理就行,40分钟才写完。看到T3,感觉不太能做,T4瞄了一眼......
  • 2024⾥昂展会见证泳池清洁⾏业3.0时代到来
    每两年举办一次的里昂泳池展(PiscineGlobal)被誉为全球泳池桑拿设备行业的“风向标”。2024年11月,这一全球规模最大、最具影响力的行业盛会在法国里昂如期举行。全球众多企业踊跃参展,展示其创新突破,其中泳池清洁机器人行业是发展最快的创新热点之一。随着技术的不断迭代,泳池清洁......
  • 神秘回忆录——我的NOIP2024游记
    前言我,厦门外国语学校(\(\text{XMFLS}\))高一历史上最菜的一位\(\text{OIER}\)。在刚刚结束不久的\(\text{CSP-S2024}\)中,获得了300pts的低分成绩,侥幸的获得了\(\text{NOIP2024}\)的参赛资格。我对此感到十分的荣幸,并写下这篇游记。回首过往,我从神秘\(\text{YLSX}\)接触......
  • CSP-J 2024总结
    这次比赛没有发挥出我的正常水平,第二题粗心爆零了,以下是我对这次比赛的总结:这次比赛的第一题比较简单,用map来查询有没有遇到过就行了,甚至不用考虑数据给你输入的是什么,只要没遇到过就让ans-1就行了;第二题当时测的样例过了,最后一分都没得,比赛后用我当时交的代码又测试了几遍,发......
  • 2024/11/30课堂记录
    目录1.机器分配2.最大食物链计数3.菜肴制作机器分配多重背包变式,改变一下计算价值的方式另外,题目里没提到要前面的公司尽量少分配,后面的公司尽量多分配,不然90分所以比较时要<=(20行)见代码,写注释了点击查看代码#include<iostream>usingnamespacestd;inta[20][20......