innodb的锁

innodb按照锁的类型划分为:

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。


加锁的方式

对于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。


一致性非锁定读:

指innodb通过多版本控制的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行del和update操作,这是读取操作不会因此去等待排他锁的释放,而是去读取行中的一个快照数据(通过事物的undo回滚机制来实现,不存在多余的开销)。

注,1,这是innodb默认的读取方式(因为select 语句默认没有加锁);

       2,不同的事物隔离级别下所认为的快照数据是不一样的,如下

Session A

Session B

begin

 

Select id from t where id = 1;

 

 

begin

 

Update t set id = 3 where id = 1;

这个时候commit的话得到的结果如下:

(read committed 级别下的结果为 1

Repeatable read 级别下的结果为1)

因为事物B还没有提交

 

 

Commit

这个时候commit的话得到的结果如下:

(read committed 级别下的结果为 3

Repeatable read 级别下的结果为1

可重复读,即这个时候在执行一遍Select id from t where id = 1;那么得到的结果也是1,也就解释了可重复读的概念)

因为事物B还没有提交

 

 

 

 

 

 

上表说明:对于read committed 其所认为的快照数据总是有事务提交之后的最新的数据;

对于Repeatable read 其所认为的快照数据总是最开始读取的到的数据。


一致性锁定读:

即通过对select 语句显示加锁的方式来实现


丢失更新

在事务并发的场景下,很容易多个事务之间产生丢失更新的情况。

如:

Session A

Session B

Begin

 

Select money from t where id = 1;

 

 

begin

 

Select money from t where id = 1;

程序逻辑检查money的余额

 

Update t set money = 300 where id = 1;

原来money为1000,转出700

 

 

Update t set money = 1300 where id = 1;

另外一个人给她转了300,即转入300

Commit

 

 

Commit

如上,由于session B最后提交,那么最后的结果为1300,其实应该为1000.

 

解决方案为,把sql  Select money from t whereid = 1 变为Select money from t where id = 1 for update;


死锁:

是指两个或者是两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。

死锁的解决方案

1,超时机制,即当两个事务互相等待的时候,当一个等待的时间超过了设定的某一个阈值,那么这个事务回滚。但是超时机制在某些情况下不合理,比如,因为超时需要回滚的事务是一个比较大的事务,那么回滚她,让她重新执行显然不合理。

2,等待图的方式(wait-for graph)。她是一种更为主动的死锁检测方式,innodb也采用这种方式。下面将会详细解释这个算法实现。

死锁的示例:

在事务并发中就可能会产生死锁,锁的粒度越小发生死锁的概率也就越大

Session A

Session B

Begin

 

Select money from t where id = 1 for update;

 

 

begin

 

Select money from t where id = 2 for update;

 

 

Select money form t where id = 2 for update;

这个时候进行等待

 

 

Select money from t where id = 1 for update;

Innodb发生错误:

Error1213

 

Innodb会回滚当前事务






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值