mysql锁,mysql锁的作用是什么
引入锁机制技术解决问题,用锁实现隔离,保证并发事务的正确性。
两把锁。一次阻止两个锁。
数据库遵循两阶段锁定协议,该协议将事务分为两个阶段,锁定阶段和解锁阶段(所谓的两阶段锁定)。
锁定阶段:锁定阶段只能进行锁定操作。如果一个事务想要读取一个对象,它必须首先获得一个共享锁。多个事务可以同时获取一个对象的共享锁。如果一个事务想要修改一个对象,它必须首先获得独占锁。只有一个事务可以获得该对象的排他锁。如果一个事务已经获得了对象的独占锁,其他试图获得锁(包括共享锁和独占锁)的事务必须等到锁成功锁定后才能继续解锁阶段:解锁阶段只能执行解锁操作。要读取对象,事务必须首先获得一个共享锁,这可以防止幻像读取。要修改对象,事务必须首先获得一个排他锁,这可以防止脏写。
两阶段锁定可以这样实现:在事务开始后处于锁定阶段,在执行rollback或commit之前处于锁定阶段。回滚和提交使事务进入解锁阶段,即回滚或提交时释放持有的锁。
封锁
一次封锁法遵守两阶段锁协议。
封锁要求每个事务必须一次性锁定所有要使用的数据,否则无法继续执行。
封锁中存在的问题:
阻塞时间延长,并发减少:一次性锁定所有未来要使用的数据,必然会延长阻塞时间,从而降低系统的并发。不适用于数据库:封锁不适用于数据库,因为在事务开始时,数据库不知道将使用哪些数据。封锁的好处:不会出现僵局。
为什么要用两把锁?用完后就不能开锁吗?
不会,用完直接释放会影响事务的隔离。详情请见以下文章。Mysql锁:灵魂的折磨7(youzan.com)
两级锁的优缺点限制两级锁的优点/功能:
解决事务并发问题:防止脏写和脏读.....................
性能:与其他弱隔离级别相比,使用两段锁大大降低了事务吞吐量和查询响应时间。部分原因是获取和释放锁的开销,但更重要的是,它降低了事务的并发性。访问延迟具有很大的不确定性:如果一个事务需要等待另一个事务释放锁,那么另一个事务释放锁的时间是不确定的,所以等待它释放锁的时间是不确定的。更频繁的死锁:由于两段锁的锁定模式,死锁可能会变得更频繁。这导致了另一个性能问题,即如果事务因死锁而被强制终止,应用层必须从头重试。如果死锁太频繁,性能和效率都会大打折扣。数据库将自动检测死锁情况,并强制中止其中一个事务以打破死锁。
因为使用了这么多锁机制,所以很容易死锁。例如,事务A可能正在等待事务B释放它的锁,而事务B正在等待事务A释放它的锁。数据库会自动检测事务间的死锁,并强制中止一个事务来打破死锁,让另一个事务继续执行。应用层需要重试中止的事务。
MySQL提供的锁按照锁的范围大致可以分为全局锁、表级锁和行级锁。
全局锁全局锁是锁定整个数据库实例。
向数据库实例添加全局锁的命令:用读锁刷新表;(FTWRL)
释放锁的命令:解锁表;(释放表级锁和行级锁也是命令)
添加全局锁后,整个数据库处于只读状态,其他线程的以下语句将被阻塞:
Update语句(数据添加、删除、更新)数据定义语句(DDL,包括建表、表结构修改等。)更新类事务的提交语句(更新类事务类似于select * from t1 for update全局锁的一个典型使用场景是对整个数据库进行逻辑备份。也就是说,整个库中的每个表都保存为. sql文件。
全局锁相当于停止更新操作并获得一致的视图。
MySQL也可以通过在可重复读取隔离级别打开事务来获得一致的视图,后者可以在不影响更新操作的情况下完成。
官方自带全逻辑备份工具mysqldump。
当mysqldump使用参数- single-transaction时,它将使用基于MVCC机制的一致性视图。当mysqldump使用参数- master-data时,它将使用基于全局读锁的一致性视图。表级锁表级锁就是锁表。
MySQL中有三种表级锁:
手表锁;元数据锁(MDL);有意锁定。表锁是锁定整个数据表。
向数据表添加表锁的命令:锁表名读/写;
释放表锁的命令与释放全局锁的命令相同:解锁表;如果没有手动释放表锁,当客户端断开连接时,它会自动释放。
需要注意的是,锁表语法不仅限制了其他线程的读写,也限制了本线程的下一步操作对象。
例如,如果锁表t1 read、t2 write在线程A中执行;这个语句会阻塞其他线程写t1和读写t2的语句。同时,线程a在执行解锁表之前只能读取t1和读写t2。连写t1都不允许,自然也就不能访问其他表了。
意向锁分为共享锁和排他锁。
如果我们想给整个数据表添加一个共享锁,我们必须首先确保表中没有被独占锁定的记录。如果我们想给整个数据表添加一个排它锁,我们必须首先确保表中没有被排它/排他锁的记录。我们可以通过遍历所有记录来检查表中是否有锁定的记录,但是遍历太慢了。
意向锁的提出是为了在表级添加共享锁和排他锁时,快速判断表中的记录是否被锁定,避免遍历表查看是否有被锁定的记录,提供判断速度。
意向锁分为意向共享锁和意向排他锁:
当一个事务准备向一个记录添加一个共享锁时,它需要先在表级添加一个有意的共享锁;当事务要在记录上添加一个排他锁时,它需要首先在表级别添加一个有意的排他锁。这样,如果表级存在有意的共享锁,就意味着表中存在带有共享锁的记录;如果在表级别存在有意的排他锁,则意味着表中存在带有排他锁的记录。我们可以通过有意锁定的方式快速判断表中是否有记录被锁定。
表锁和意向锁之间的兼容和互斥关系
有意共享锁和有意排他锁是兼容的。表锁和意向锁之间的兼容和互斥关系如下:
:heavy_check_mark:表示它们兼容;X:表示它们是互斥的。锁的类型
有意锁定
有意排他锁
表共享锁
:重选标记:
:x:
表排他锁
:x:
:x:
如果表持有有意的共享锁,也就是说表中的一条记录持有共享锁,那么表共享锁就可以被成功锁定;锁定表独占锁失败,阻塞等待。如果表持有预期的排他锁,这意味着表中有持有排他锁的记录,则表共享锁和表排他锁的锁定失败。MySQL版本5.5中引入了阻塞等待元数据锁(MDL)。
MDL不需要显式使用,访问表时会自动锁定。
MDL锁分为:MDL读锁和MDL写锁:
DML操作(数据添加、删除和查询:插入、删除、更新和选择)加MDL读锁DDL操作(表结构改变操作)加MDL写锁。锁定和释放MDL锁的规则:
MDL读锁和MDL读锁互不干扰。MDL写锁和MDL写锁,MDL写锁和MDL读锁互相阻塞。用于确保表结构更改操作的安全性。MDL锁使用两个锁:在事务获得锁之后,它持有锁,直到事务结束(包括提交或中止)。MDL锁的作用是防止DDL操作和DML操作的并发,保证表结构改变操作的安全性。
需要注意的是,如果申请MDL锁失败,那么所有后续的锁申请都必须等待(公平锁机制,遵循先来先执行的原则,先来的不成功,后面的不能锁)。因此,在执行DDL操作时要特别注意。如果操作时间过长,后续的DML操作将会被阻塞很长时间。
行级锁行级锁就是锁定记录。
行级锁分为各种类型,不同类型的行级锁有不同的功能。行级锁分为:
记录:行锁,单行记录的锁间隙锁:间隙锁,作用于记录之间的间隙,仅用于防止符合搜索条件的记录插入间隙(防止插入幻影记录)下一键锁:索引区间锁,本质上是行锁和间隙锁的组合。间隙锁意味着间隙锁是对索引记录之间的间隙的锁,或者是对第一个或最后一个索引记录之前或之后的间隙的锁。例如,从t中选择c1,其中c1介于EN 10和20之间,用于更新;防止其他事务将值15插入到t.c1列中,无论该列中是否已经有任何这样的值,因为该范围中所有现有值之间的间隔被锁定。只有在可重复读取或高于隔离级别时,才会为特定操作添加间隙锁。添加带读写锁的select、update、delete时,除了基于唯一索引的查询(主键索引也是唯一索引)外,基于其他索引的查询都会添加gap锁。
能够添加间隙锁的要求:
必须反复阅读或以上。如果选择了它,则必须通过向读取记录添加读写锁来重复读取它。挑选.对于更新,请选择.在共享模式下锁定,以及以上两种手动共享锁定。排他锁的方式必须是索引查询。如果是全表扫描查询,就没有办法添加间隙锁。锁定规则:包含两个“原则”,两个“优化”,一个“bug”。
原则1:锁的基本单元是next-key锁。下键锁是前开后关的间隔。原则2:只有在搜索过程中访问的对象才会被锁定。1:优化:对索引的等价查询,当唯一索引被锁定时,next-key锁退化为行锁。2.优化:当索引上的等价查询向右遍历,最后一个值不满足等价条件时,next-key锁退化为gap锁。Bug:对唯一索引的范围查询将访问第一个不符合条件的值。共享锁和排他锁说明表锁、元数据锁和行锁都分为共享锁和排他锁。
共享锁——共享锁兼容性:如果一个事务想要读取一个对象,它必须首先以共享模式获取锁。多个事务可以同时获取一个对象的共享锁。共享锁-排他锁、排他锁-排他锁是互斥的:如果一个事务想要修改一个对象,它必须首先以排他模式获取锁。只有一个事务可以获得该对象的排他锁。如果一个事务已经获得了对象的独占锁,其他试图获得该锁(包括共享锁和独占锁)的事务必须等待共享锁和独占锁之间的兼容互斥关系,如下所示:
:heavy_check_mark:表示它们兼容;X:表示它们是互斥的。锁的类型
共享锁
互锁
共享锁
:重选标记:
:x:
互锁
:x:
:x:
为什么要分共享锁和独占锁?允许多个事务并发读,但只允许一个事务写,既支持并发提高性能,又保证并发安全。
版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。