mysql锁的操作_MySQL的锁操作

Mysql  InnoDB引擎中锁的介绍

1.    共享锁:允许事务读一行数据

2.     排他锁:允许事务删除或者更新一行数据

3.     意向共享锁:事务想要获得表中某几行的共享锁,是表级锁

4.     意向排他锁:事务想要表中某几行的排他锁

查询锁信息的方法

查看当前请求锁定的信息:show engine innodb status

查看锁的具体信息:select * frominformation_schema.innodb_locks

查看锁的等待消息:select * from information_schema.innodb_lock_waits

Innodb的非锁定读工作原理

Innodb的select操作使用的是一致性非锁定读,即如果读取的行正在执行delete  update操作,这时读取操作不会等待行上锁的释放,而是去读取行的一个快照数据,快照数据是指在行修改之前的版本的数据,该实现是通过undo段实现的,但是不同事物隔离级别下,读取的方式不同,并不是每个事物隔离级别的读取都是一致性读。

例如:read committed级别,总是读取行的最新版本,如果行被锁定了,读取该行版本的最新一个快照,一个事务在开始时只能看见已经提交的事务所做的改变,在事务提交前所做的任何数据都是不可见的;repetable read(默认事务级别)总是读取事务开始时的行数据,但会导致幻读,比如当用户读取某一范围内的数据行时,另一个事务又在该范围内插入了新行,当用户再次读取该范围内的数据行时,会发现有新的幻影行,不过innodb的多版本并发控制机制可解决幻读问题;read uncommitted级别所有事务都能看见为提交事务的执行结果,这样可能会产生很多问题,比如脏读,建议不采纳这种隔离级别;serializable是最高的隔离级别,它通过强制事务排序,使之不可能发生相互冲突,从而解决幻读问题,也就是它在每个读的数据行上加锁。但在这个级别肯能导致大量地超时现象和锁竞争现象,很少采纳,除非是用户的应用是为了数据的稳定性,需要强制减少并发的情况下。

显示加锁的方法

非锁定读大大提高了数据读取的并发性,这时默认读取方式,也可以显示地给select加锁,方法如下:

Select …. For  update  对读取的行记录加一个X锁,其他事务想在这些行上加锁会被阻塞;

Select …. Lock in share mode  对读取的行记录加一个S锁,其他事务可以对锁定的记录加S锁,但不能加X锁

Innodb的行锁算法

InnoDB有3种行锁的锁的算法,分别是

Record Lock:单个行记录上的锁

Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

Next-Key Lock(默认):锁定一个范围,并且包括记录本身,相当于Reacord+Gap

下面通过一个例子演示一下Next-Key Lock算法:

先建一张表testlock,向其中插入数据1,2,3,4,7,8

开启会话A:开启一个事务但不提交,代码如下:

set autocommit = 0;

start transaction;

select * from test.locktest where idlocktest< 7 lock in share mode;

开启会话B,插入一个值为10的数据:

Insert into test.locktest values (10);

Insert into test.locktest values (6);

结果发现数据10 能插入,6 不能插入,一直在运行,因为该锁算法锁定的是一个范围,而6在范围内,这时在会话A commit,此时就发现会话B中执行完成了~~

锁带来的问题

1.     丢失更新,让事务变成串行操作,而不是并发的操作,即对每个事务开始就对读取记录加排他锁

2.     脏读:一个事务读到另一个事务中为提交的数据,发生的条件是read uncommitted

3.     不可重复读:读的是已经提交的数据。可忽略。

乐观锁和悲观锁

悲观锁:指的是假设并发更新冲突会发生,所以不管冲突是否真的发生,都会用锁机制,完成下面功能:锁住读取的记录,防止其他事务读取和更新这些记录,其他事务会一直被阻塞,直到这个事务结束,可用repeatable read事务实现,还可以用for update语句实现

乐观锁:不会锁住任何东西,也就是说它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西,使用乐观锁必须加版本字段,否则只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不行的。

locktables 和unlock tables指令

注意点:mysql支持locktables 和unlock tables指令,这是由服务器实现的,和存储引擎无关,当一个应用从myisam转成innodb时没必要使用这些指令了,因为innodb支持行级锁,况且这种命令会影响服务器的性能。

多版本并发控制(MVCC)

非mysql特有,通过及时保存在某些时刻的数据快照得以实现,意味着同一事务的多个实例在共同运行时,无论每个实例运行多久,他们看到的数据视图是一样的,而在同一时间同一张表,不同事务事务看到的数据却是不同的!下面以innodb方式简化MVCC工作原理:innodb通过为每个数据行添加两个隐含值得方式实现mvcc,这两个隐含值记录了行的创建时间和删除时间,每一行都存储了事件发生时的系统版本号,用来替换事件发生时的实际时间,每一次开始一个新事务时,版本号会自动递增,每个事务都会保存它在开始时的当前系统版本的记录,而每个查询都会根据事务的版本号检查每行数据的版本号。

Select:

必须确保符合两个标准:

1 innodb只查找版本早于当前事务版本的数据行,这确保了当前事务读取的行都是在事务开始前已经存在的或是当前事务创建和修改的行

2 数据行的删除版本必须是未定义的,或大于事务版本,这确保了事务读取的行,在事务开始时是未被删除的

Insert: innodb为每个新增行记录下当前系统版本号

Delete:innodb为每个删除行记录下当前系统版本号作为删除标示

Update:为每个需要更新的行,建立一个新的行拷贝,并且为新的行拷贝记录当前的系统版本号,同时也为更新前的旧行记录了系统的版本号,作为旧行的删除版本标示

这样做的好处是使得大多数读操作不必申请加锁,使得读操作尽可能地快,并发程度就提高了,缺点是必须为每行数据存储更多的额外数据,做更多的行检查工作。MVCC只支持read和committed两个隔离级别!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值