精华内容
下载资源
问答
  • 共享锁和共享锁可以兼容
    2021-01-28 00:59:41

    nnoDB的行锁模式及加锁方法

    InnoDB实现了以下两种类型的行锁。

     共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

     排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

    另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。

     意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

     意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

    上述锁模式的兼容情况具体如表20-6所示。

    表20-6     InnoDB行锁模式兼容性列表

    请求锁模式

    是否兼容

    当前锁模式

    X

    IX

    S

    IS

    X

    冲突

    冲突

    冲突

    冲突

    IX

    冲突

    兼容

    冲突

    兼容

    S

    冲突

    冲突

    兼容

    兼容

    IS

    冲突

    兼容

    兼容

    兼容

    如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。

    意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

    ·共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。

    ·排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

    用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。

    在如表20-7所示的例子中,使用了SELECT ... IN SHARE MODE加锁后再更新记录,看看会出现什么情况,其中actor表的actor_id字段为主键。

    表20-7           InnoDB存储引擎的共享锁例子

    session_1

    session_2

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    当前session对actor_id=178的记录加share mode 的共享锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.01 sec)

    其他session仍然可以查询记录,并也可以对该记录加share mode的共享锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.01 sec)

    当前session对锁定的记录进行更新操作,等待锁:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    等待

    其他session也对该记录进行更新操作,则会导致死锁退出:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    获得锁后,可以成功更新:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    Query OK, 1 row affected (17.67 sec)

    Rows matched: 1  Changed: 1 Warnings: 0

    当使用SELECT...FOR UPDATE加锁后再更新记录,出现如表20-8所示的情况。

    表20-8             InnoDB存储引擎的排他锁例子

    session_1

    session_2

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    当前session对actor_id=178的记录加for update的共享锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    其他session可以查询该记录,但是不能对该记录加共享锁,会等待获得锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE   |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

    等待

    当前session可以对锁定的记录进行更新操作,更新后释放锁:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    Query OK, 1 row affected (0.00 sec)

    Rows matched: 1  Changed: 1 Warnings: 0

    mysql> commit;

    Query OK, 0 rows affected (0.01 sec)

    其他session获得锁,得到其他session提交的记录:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE T |

    +----------+------------+-----------+

    1 row in set (9.59 sec)

    更多相关内容
  • 本文全面讲解了MySQL中锁包括表锁,行锁,共享锁,排它锁,间隙锁的详细使用方法
  • 前言: 最怕面试官问到一大堆的锁概念了,表锁、页锁、行锁,排它锁、共享... 本文就着示例把InnoDB中的行锁的两种标准实现:共享锁和排它锁分析一下 准备: 1)笔者新建了张表(实际是copy的其他表),city...

    前言:

        最怕面试官问到一大堆的锁概念了,表锁、页锁、行锁,排它锁、共享锁...

        有关于锁的概念实在太多了,而我们在实际使用中使用到的又太少。很少有专门去写特定类型的锁实现,一般都是数据库默认帮我们做了相应的锁动作。

        本文就着示例把InnoDB中的行锁的两种标准实现:共享锁和排它锁分析一下

     

    准备:

        1)笔者新建了张表(实际是copy的其他表),city_copy表,主键为ID,自增长模式,默认从1开始。表创建SQL如下:

    CREATE TABLE `city_copy`  (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `Name` char(35) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '',
      `CountryCode` char(3) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '',
      `District` char(20) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '',
      `Population` int(11) NOT NULL DEFAULT 0,
      PRIMARY KEY (`ID`) USING BTREE,
      INDEX `CountryCode`(`CountryCode`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4080 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

        2)有关于InnoDB事务和锁记录的几张表

            information_schema.INNODB_TRX:事务信息表

            information_schema.INNODB_LOCKS:锁信息表

            information_schema.INNODB_LOCK_WAITS:锁等待信息表

     

    1.共享锁事务之间的读取

        1)session1(共享锁)

    set autocommit=0; ##首先就是关闭自动提交
    select * from city where id < 4 lock in share mode; ##以共享模式读取数据
    
    select * from information_schema.INNODB_TRX; ##查询事务信息

        查询事务结果值:

        可以看到,当前SQL执行完成之后存在已经RUNNING(运行中)的事务,锁定记录数为4行

     

        2)session2(共享锁)

        与session1执行相同的动作

    set autocommit=0; ##首先就是关闭自动提交
    select * from city where id < 4 lock in share mode; ##以共享模式读取数据
    
    select * from information_schema.INNODB_TRX; ##查询事务信息

        结果就是:出现两条RUNNING事务记录,两个select语句分别都执行成功,获取到结果值

        两个session分别执行commit之后,运行中的事务信息消息。说明事务结束。

     

        总结:共享锁与共享锁之间是相互兼容的。

     

    2.共享锁与排它锁的事务示例

        1)session1(共享锁)

    set autocommit=0; ##首先就是关闭自动提交
    select * from city where id < 4 lock in share mode; ##以共享模式读取数据
    
    select * from information_schema.INNODB_TRX; ##查询事务信息

        session1执行共享锁读取方式,结果与1相同,不再展示

     

        2)session2(排它锁)

    set autocommit=0; ##首先就是关闭自动提交
    select * from city where id < 4 for update; ##以排它锁的方式读取
    select * from information_schema.INNODB_TRX; ##查询事务信息
    
    // res 事务结果值如下
    trx_id	trx_state	trx_started	trx_requested_lock_id	trx_wait_started	trx_weight	trx_mysql_thread_id	trx_query	trx_operation_state	trx_tables_in_use	trx_tables_locked	trx_lock_structs	trx_lock_memory_bytes	trx_rows_locked	trx_rows_modified	trx_concurrency_tickets	trx_isolation_level	trx_unique_checks	trx_foreign_key_checks	trx_last_foreign_key_error	trx_adaptive_hash_latched	trx_adaptive_hash_timeout	trx_is_read_only	trx_autocommit_non_locking
    462611	LOCK WAIT	2019-12-28 18:01:58	462611:50:5:2	2019-12-28 18:01:58	2	9	select * from city where id < 4 for update	starting index read	1	1	2	1136	1	0	0	REPEATABLE READ	1	1		0	0	0	0
    284711444560536	RUNNING	2019-12-28 18:01:38			2	10	select * from information_schema.INNODB_TRX		0	1	2	1136	4	0	0	REPEATABLE READ	1	1		0	0	0	0

        根据事务结果值可以看到,与之前的状态有所不同

        id=284711444560536的事务是session1的共享锁事务;

        id=462611的事务是session中的排它锁事务,目前是锁等待状态(表现形式就是目前获取不到select结果值,一直在转圈执行),这个会一直等待session1锁释放或者session2锁超时时候回滚

     

        总结:共享锁与排他锁是互不兼容的。

        读者也可以试试,先执行session2再执行session1,结果值也是互不兼容的。

     

    总结:

        1.我们首先需要记住的是:共享锁和排它锁都是行锁类型,所以上述的例子都是锁定id <4的这些数据行,如果两个session锁定的是不同的行记录,那么就不存在兼不兼容的问题了。

        2.排它锁的获取方式除了上述例子中的select ... for update,还有就是update 、delete操作

        3.共享锁与共享锁之间是相互兼容的

        4.共享锁与排它锁之间是互不兼容的

     

    参考:MySQL技术内幕 InnoDB存储引擎

    展开全文
  • 想要学好 mysql 数据库,机制的理解才是打开通往更深层次大门的钥匙

    目录

    一、常见锁类型

    二、Mysql引擎介绍

    三、常用引擎间的区别 

    四、共享锁与排他锁

    五、排他锁的实际应用

    六、共享锁的实际应用

    七、死锁的发生

    八、另一种发生死锁的情景

    九、死锁的解决方式

    十、意向锁和计划锁

    十一、乐观锁和悲观锁


    一、常见锁类型

    • 表级锁,锁定整张表
    • 页级锁,锁定一页
    • 行级锁,锁定一行
    • 共享锁,也叫S锁,在MyISAM中也叫读锁
    • 排他锁,也叫X锁,在MyISAM中也叫写锁
    • 悲观锁,抽象性质,其实不真实存在
    • 乐观锁,抽象性质,其实不真实存在
    常见锁类型

    二、Mysql引擎介绍

    • 其实mysql中的引擎有很多种类,其中InnoDB和MyISAM引擎最常用
    • 在mysql5.5版本前默认使用MyISAM引擎,之后使用InnoDB引擎
    • 查看数据库引擎命令如下
    show variables like '%storage_engine%';

    三、常用引擎间的区别 

    • MyISAM 操作数据都是使用的表锁,你更新一条记录就要锁整个表,导致性能较低,并发不高。当然同时它也不会存在死锁问题。

    • 而 InnoDB 与 MyISAM 的最大不同有两点:一是 InnoDB 支持事务;二是 InnoDB 采用了行级锁。

    • 在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。

    • InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。

    四、共享锁与排他锁

    • 数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。

    • 共享锁:对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源(也可以再继续加共享锁,即 共享锁可多个共存),但无法修改。要想修改就必须等所有共享锁都释放完之后。

    • 排他锁:对某一资源加排他锁,自身可以进行增删改查,其他人无法进行任何操作。

    //共享锁
    select * from 表名 lock in share mode
    
    //排他锁
    select * from 表名 for update

    五、排他锁的实际应用

    • 这里我们以两个操作数据库的请求为例,假设这两个请求分别为T1和T2
    • 假设T1为查询请求,而T2为更新数据请求,在T1查询很长时间的时候,还没有返回结果,但是这时候T2过来请求更新了
    • 这个流程应该是: T1运行加共享锁、T2运行、发现T1未完成等待其完成、T1完成、T2开始执行
    • T2之所以要等待,是因为T2执行更新的时候需要给表加排他锁,但是数据库规定,不能在同一资源上同时共存这两种锁,所以T2必须等T1执行完,释放锁后,才可以正常操作
    T1: select * from 表名 lock in share mode //假设还未返回结果
    
    T2: update 表名 set name='autofelix'

    六、共享锁的实际应用

    • 如果T1和T2都是执行的查询,也就是都加共享锁
    • 这时候就不用等待,可以立马执行
    • 因为同一资源上可以同时存在多个共享锁,也被称为,共享锁与共享锁兼容
    • 意味着共享锁不阻止其他人同时读取资源,但是阻止其他人修改资源
    T1: select * from table lock in share mode
    
    T2: select * from table lock in share mode

    七、死锁的发生

    • 假设T1和T2都同时执行2个资源操作,分别是查询和更新数据
    • 假设T1和T2同时达到select,T1对表加共享锁,而T2也加上了共享锁
    • 当T1的select执行完毕,准备执行update时
    • 根据锁机制,T1的共享锁必须升级到排他锁才可以执行接下来的update操作
    • 在升级排他锁之前,必须等T2的共享锁释放,同理,T2也在等T1的共享锁释放
    • 于是都在等待对方的锁释放,导致程序卡死,这种情况就是死锁
    T1: 开启事务,执行查询更新两个操作
    
         select * from table lock in share mode
    
         update table set column1='hello'
    
    T2: 开启事务,执行查询更新两个操作
    
         select * from table lock in share mode
    
         update table set column1='world'

    八、另一种发生死锁的情景

    •  当T1和T2都是只执行更新语句的时候
    • 如下程序所示,这种语句非常的常见,很多人觉得他会产生死锁,其实要看情况
    • 如果id是主键,由于主键机制,并不需要全表扫描,直接可以更新当前数据,所以不会产生死锁
    • 如果id是普通字段,那么当T1加上排他锁之后,T2为了找到id=20条数据,必须进行全表扫描,当他扫到第10条的时候,发现这里有排他锁,导致全表扫描进行不下去,就会导致等待
    T1: begin
         update table set content='hello' where id=10
    
    T2: begin
         update table set content='world' where id=20

    九、死锁的解决方式

    • 就是让T1和T2顺序执行,比如T1在执行完select后,立马给自身加上排他锁,这样T2不得不等待T1执行完才能继续
    • 但是如果有很多请求过来的话,都必须等待,这对用户特别的不友好
    • 所以,某些数据库引入了另一种方式,叫做更新锁,这里mysql除外,不存在更新锁
    • 更新锁其实就是排他锁的另一种实现,只是他允许其他人读的同时加共享锁,但是不允许其他操作,除非释放了更新锁
    • 流程大概如此: T1执行完select加上更新锁,T2执行查询完,准备加更新锁,发现已经有了,就等待,其他请求过来,如果查询是不受影响的,但是更新才等待
    • 这相比上面的查询也要等待增加了效率
    T1: begin
    
         select * from table for update
    
         update table set content='hello'
    
    T2: begin
    
         select * from table for update
    
         update table set content='world'
    T1: begin
    
         select * from table [加更新锁操作]
    
         update table set content='hello'
    
    T2: begin
    
         select * from table [加更新锁操作]
    
         update table set content='world'

    十、意向锁和计划锁

    • 计划锁与程序猿无关,不需要了解
    • 意向锁,Innodb特有,分为意向共享锁和意向排他锁
    • 意向共享锁: 表示事务获取共享锁时,必须先得获取该表的意向共享锁
    • 意向排他锁: 表示事务获取排他锁时,必须先得获取该表的意向排他锁
    • 我们知道要对整个表加锁,必须保证表内不存在任何锁
    • 如果一行行的去检查是否加锁,效率必然极低,这时候可以检测意向锁是否被占用即可

    十一、乐观锁和悲观锁

    • 乐观锁和悲观锁都是针对select而言的
    • 比如在商品抢购中,用户购买后库存需要减1,而很多用户同时购买时,读出来的库存数量一样,然后多个用户同时用该库存去减1
    • 这种做法必然会出现很大的漏洞,如果向在淘宝,京东出现这种情况,你就可以打包回家种地了
    • 这种情况如何解决呢,其实可以使用悲观锁进行解决,说白了也就是排他锁
    • 用户进来查库存的时候,就加上排他锁,等他所有操作完成后,再释放排他锁,让其他人进来
    • 不让用户等待,就可以使用乐观锁方式解决,乐观锁一般靠表的设计和时间戳来实现
    • 一般是在表中添加version或者timestamp时间戳字段
    • 这样就会保证如果更新失败,就表示有其他程序更新了数据库,就可以通过重试解决
    update table set num=num-1 where id=10 and version=12 
    展开全文
  • 本设计分享的是基于MC20定位共享单车智能设计,支持蓝牙4.1/GPRS定位。该共享单车智能电路主要由电源模块、MC20GPRS定位...注意:MC20定位共享单车智能电路原理图PCB用PADS9.5打开,PCB截图如下: 附件内容截图:
  • 一、InnoDB表级锁 二、意向共享锁和意向排他锁 三、死锁 1. 数据库中的死锁 2. 死锁场景以及解决办法 3. 操作 四、锁的优化建议

    一、InnoDB表级锁

    我们知道,InnoDB是支持行锁,但不是每次都获取行锁,如果不使用索引的,那还是获取的表锁。而且有的时候,我们希望直接去使用表锁

    在绝大部分情况下都应该使用行锁,因为事务的并发效率比表锁更高,但个别情况下也使用表级锁:

    • 事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,给大部分行都加锁(此时不如直接加表锁),不仅这个事务执行效率低,而且可能造成其他事务长时间等待和锁冲突
    • 事务涉及多个表,比较复杂,如果都用行锁,很可能引起死锁,造成大量事务回滚

    当我们希望获取表锁时,可以使用以下命令:

    LOCK TABLE user READ  -- 获取这张表的读锁
    LOCK TABLE user WRITE -- 获取这张表的写锁
    
    事务执行…
    
    COMMIT/ROLLBACK;      -- 事务提交或者回滚
    UNLOCK TABLES;        -- 本身自带提交事务,释放线程占用的所有表锁
    

    在使用表锁的时候,涉及到效率的问题:
    如果我们要获取一张表的排它锁X,最起码得确定,这张表没有被其他事务获取过S锁或X锁,以及这张表没有任何行被其他事务获取过行S或X锁

    假如这张表有1000万个数据,那我怎么知道这1000万行哪些有行锁哪些没有行锁呢?

    除了挨个检查,没有更好的办法,这就导致效率低下的问题

    我们这里学习的意向共享锁和意向排他锁就是用来解决,由于需要加表锁而去挨个遍历数据,确定是否有某些数据被加了行锁,而导致的效率低下问题

    二、意向共享锁和意向排他锁

    为了可以更快速的获取表锁

    意向共享锁(IS锁):事务计划给记录加行共享锁,事务在给一行记录加共享锁前,必须先取得该表的IS锁
    意向排他锁(IX锁):事务计划给记录加行排他锁,事务在给一行记录加排他锁前,必须先取得该表的IX锁

    在这里插入图片描述

    1. 在加行锁之前,由InnoDB存储引擎加上表的IS或IX锁
    2. 意向锁之间都兼容,不会产生冲突
    3. 意向锁存在的意义是为了更高效的获取表锁(表格中的X、S、IX、IS指的是表锁,不是行锁)
    4. 意向锁是表级锁,协调表锁和行锁的共存关系,主要目的是显示事务正在锁定某行或者试图锁定某行。

    分析事务1获取行X锁和事务2获取表S锁

    首先事务1需要给表的第10行数据加X锁,于是InnoDB存储引擎自动给整张表加上了IX锁。当事务2再想获取整张表的S锁时,看到这张表已经有别的事务获取了IX锁了,就说明这张表肯定有某些数据被加上了X锁,这就导致事务2不能给整张表加S锁了。此时事务2只能等待,无法成功获取表S锁

    三、死锁

    1. 数据库中的死锁

    MyISAM 表锁是 deadlock free 的, 这是因为 MyISAM 不支持事务,只支持表锁,而且总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。如果是处理多张表,还是可能出现死锁问题的

    在这里插入图片描述
    在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,即锁的粒度比较小(行锁),这就决定了在 InnoDB 中发生死锁是可能的

    死锁问题一般都是我们自己的应用造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题。因此我们应用在对数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题

    2. 死锁场景以及解决办法

    死锁出现的场景如下:

    事务1成功获取行锁1
    事务2成功获取行锁2

    事务1无法获取行锁2,被阻塞的同时也无法释放行锁1
    事务2无法获取行锁1,被阻塞的同时也无法释放行锁2

    在这里插入图片描述

    此时所有的事务都阻塞住了,相当于进程内的所有线程都阻塞住了,发生了死锁问题

    解决死锁办法:多个事务/线程获取多个相同资源锁的时候应该按照同样的顺序获取锁。与此同时,由于mysqld(MySQL Server守护进程)设置了事务阻塞的超时时间,事务不会阻塞很长时间,超时后事务处理失败,自动释放当前占有的锁

    3. 操作

    设置自动提交 以及 可重复读隔离级别,开启事务
    在这里插入图片描述
    查询一下表数据,在可重复读隔离级别使用的是MVCC提供的快照读,并没有加锁
    在这里插入图片描述
    事务1获取id=7的排他锁,事务2获取id=8的排他锁
    在这里插入图片描述
    事务1再次获取id=8的排他锁,发生阻塞
    在这里插入图片描述
    事务2再次获取id=7的排他锁
    在这里插入图片描述
    此时由于MySQL Server检测到发生了死锁,于是解除事务1的阻塞,进行事务1的rollback,释放其占有的行锁,于是事务2成功获取id=7的排他锁

    四、锁的优化建议

    • 在能正确完成业务的前提下,为确保效率,尽量使用较低的隔离级别(必须避免脏读)

    • 设计合理的索引并尽量使用索引访问数据,使加锁更准确,减少锁冲突的机会,提高并发能力

    • 选择合理的事务大小,小事务发生锁冲突的概率小(事务越大,包含的SQL越多,可能包含更多的表资源和行资源的锁,增大了锁冲突的概率)

    • 不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会

    • 尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响(其实等值查询也会加间隙锁)

    • 不要申请超过实际需要的锁级别

    • 除非必须,查询时不要显示加锁(在已提交读和可重复读隔离级别,MVCC提供了读取机制,不需要手动加锁)

    展开全文
  • MySQL表锁、行锁、排它锁和共享锁

    千次阅读 2022-03-21 12:09:31
    一、事务隔离机制的选择 二、表级锁&行级锁 三、排它锁(Exclusive)和共享锁(Shared) 1. 测试不同事务之间排它锁和共享锁兼容性 2. 测试行锁加在索引项上 四、串行化隔离级别测试
  • 事务-》事务的ACID特性-》事务的隔离性-》事务要能够允许并发执行-》数据的安全性,一致性并发的效率问题-》事务的隔离级别 串行化-》靠实现,通过给所有的事务都排个序,并发的效率就太低了,但是数据的安全...
  • 排他锁和共享锁

    千次阅读 2018-10-11 22:13:55
    出差的时候看见一个做BO的大牛写了这样一个SQL。select name from user for update,看的我是一脸懵逼,完全没有见过,好吧只能怪自己见识少了。...我们可以用商场的试衣间来做个比喻,商场里得每个试衣间都可供多个...
  • 的概述一. 为什么要引入多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:丢失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统脏读A用户修改了...
  • 文章目录前言:共享锁和排它锁LOCK TABLES UNLOCK TABLES 语句意向锁记录锁Record Locks间隙锁 Gap Locks下一键锁定 next-key插入意图锁 前言: 与sql标准不同的地方在于innodb存储引擎在可重读事务隔离级别下...
  • MySQL之锁和事务

    2020-12-14 08:34:32
    可以按照的粒度把数据库分为表级锁和行级。 表级 对当前操作的整张表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发冲突的概率最高,并发度最低,MyISAM InnoDB引擎...
  • 共享锁和排他锁

    千次阅读 2013-10-16 16:09:10
    共享锁(S锁): 如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。 排他锁(X锁): 如果事务T对数据A加上排他锁后,则其他事务不能再对A...
  • 一、共享锁 什么是共享锁:简单来说就是该锁锁定的资源只能进行读取,不能进行增删改操作,直到该锁释放。 example 1: 请求1:select * from tabletest 请求2:update tabletast set .... 数据库执行请求1的...
  • 又称读锁(S锁),共享锁不阻塞其他事务的读操作,但阻塞写操作,同一数据对象A可以共存多个共享锁,这被称为共享锁兼容。 当T1为数据对象A加上共享锁后,可以对A进行读操作,但不能进行写操作,并且T2可以再次对A加...
  • 本文通过代码实操讲解了如何使用 python 实现简单的共享锁和排他锁。 上篇文章回顾:记一次容量提升5倍的HttpDns业务Cache调优 共享锁和排它锁 1、什么是共享锁 共享锁又称为读锁。 从多线程的角度来讲,共享...
  • 锁更新锁(*U*pdate locks)共享锁(*S*hared locks)排他锁(e*X*clusive locks)意图锁定(*I*ntent locks)ISIX 更新锁(Update locks) 更新锁定是共享锁定排他锁定的混合。共享锁是在DML执行之前进行更改之前使用...
  • 锁机制 NOLOCKREADPAST的区别。...NOLOCK表明没有对数据表添加共享锁以阻止其它事务对数据表数据的修改。 SELECT * FROM Customer 这条语句将一直死锁,直到排他锁解除或者锁超时为止。(注:设置锁超时
  • |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁) |--悲观锁(抽象性,不真实存在这个锁) |--乐观锁(抽象性,不真实存在这个锁) 二、InnoDB与MyISAM Mysql 在5.5之前默认使用 MyISAM 存储...
  • 一.S锁X锁 兼容性 加锁方式 ...共享锁 加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁 ...1)意向共享锁(IS锁):事务在请求S锁前,要先获得IS锁 2)意向排他锁(IX锁):事务在请求X锁前,要先获
  • Mysql共享锁, 排他锁意向锁的简单总结共享锁(Share Lock)排他锁(Exclusive Lock)意向锁(Intent Lock)InnoDB的两种表意向锁加锁过程说明各锁之间兼容详情表 共享锁(Share Lock) 共享锁又称读锁, 缩写(S)锁. 共享锁...
  • 共享锁、S锁、读锁都是这位朋友的别名。 我,喜欢叫他 共享读锁 。 ps:不是我乱起的名字 A shared (S) lock permits the transaction that holds the lock to read 。 共享锁允许持有该锁的事务读取。 从...
  • 而且跨平台开发中,在业务逻辑里写不同平台的兼容代码,容易造成过多的冗余,以及代码结构过于复杂的问题。为了提供一种统一的调用方式,封装一套跨平台的互斥还是有必要的。 本资源在Windows、Linux、Android、...
  • Mysql共享锁、排他锁、悲观锁、乐观锁及其使用场景 一、相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁定一行) |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁...
  • 共享锁(Shared Lock)受到隔离级别的控制,隔离级别影响Shared Lock的申请释放: 在 Read Uncommitted隔离级别下,读操作不会申请Shared Lock; 在 Read Committed(不使用row-versioning),Repeatable ...
  • mysql共享锁、排他锁、意向锁

    千次阅读 2019-07-23 15:21:45
    1.意向排他锁共享锁与排他锁冲突 (锁住一行的写锁,其他...2.意向共享锁和共享锁兼容排他锁冲突 (锁住一行的读锁,另一事务可获取该表的读锁,不可获取该表的写锁) 3.意向锁之间相互兼容 (行锁之间不冲突)
  • 的概述 一. 为什么要引入 多个用户同时对数据库 的并发操作时会带来以下数据不一致的问题: 丢 失更新 A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 脏读 A...
  • 的类型和兼容

    千次阅读 热门讨论 2016-09-11 21:02:37
    当我们使用单击版的系统时,根本不需要考虑并发量,但现在我们很多的系统都会有大量用户,我们就不得不面对并发,当出现并发...共享锁主要用于读写数据操作,它是非读占的,允许其他事务同时读取其锁定的资源,但不允
  • 的概述一. 为什么要引入多个用户同时对数据库 的并发操作时会带来以下数据不一致的问题:丢 失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统脏读A用户修 改...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 55,715
精华内容 22,286
关键字:

共享锁和共享锁可以兼容