数据库悲观锁怎么实现,mysql悲观锁实现原理
MySQL 5.5或更高版本默认采用innoDb数据引擎。 本文采用了默认的存储引擎。
乐观摇滚
乐观锁定实际上是逻辑思想,而不是mysql数据库的特性。 这要区分清楚。
有两种方法实现数据版本。 第一种方法是使用版本号,另一种方法是使用时间戳。
使用方法:
/**伪代码number库存goods_id商品id版本号默认为0 **/
$ SQL=' selectnumberfromgoodswheregoods _ id={ $ goods _ id }和版本={ $ version } ';
//以时间戳方式查询库存
$ SQL=' selectnumberfromgoodswheregoods _ id={ $ goods _ id } andtimetime (
$RS=MySqli_query($Conn,$sql );
$row=$rs-fetch_assoc (;
if($Row('number ' )0) )//通过高合并进行超卖
if($row['number']
返回插入日志('库存短缺',3,$username );
}
//库存减少
$ SQL=' updategoodssetnumber=number-{ $ number },version=1where goods _ id={ $ goods _ id } and number0';
//用时间戳的方式减少库存
$ SQL=' updategoodssetnumber=number-{ $ number },time=time (where goods _ id={ $ goods _ id } and number0';
$store_RS=MySQLI_query($Conn,$sql );
if($store_RS ) {
//生成订单,回复操作成功
echoJSON_encode(Array('code'=0,' msg'='库存减少成功',' data'=$username );
}else{
echoJSON_encode(Array('code'=1,' msg'='库存减少失败',' data'=$username ) );
}
}else{
echoJSON_encode(Array('code'=3,' msg'='库存减少失败',' data'=$username ) );
}
注意:使用乐观锁定需要注意。 库存字段number字段设置为unsigned,如果库存为0,则字段不能为负数,因此返回false
悲观摇滚
悲观锁定是指在数据处理过程中数据被锁定,因为它对本系统当前的其他事务和外部数据(包括来自外部系统的事务)的修改是保守的。 悲观锁定的实现往往取决于数据库提供的锁定机制。 此外,只有数据库层提供的锁定机制才能真正保证数据访问的排他性。 否则,在本系统中实现锁定机制并不能保证外部系统不会修改数据。
悲观锁利用了支持MySQL innoDB存储引擎行锁的特性。 一行一行的操作数据。
使用方法:
//使用悲观锁定锁定当前行
$ SQL=' selectnumberfromgoodswheregoods _ id={ $ goods _ id } for update ';
//减少库存操作
$ SQL=' updategoodssetnumber=number-{ $ number } where goods _ id={ $ goods _ id } and number0';
注意: innoDB行锁定基于索引执行。 where条件之后需要索引。 否则,前进到全表扫描。
利弊:
悲观控制实际上是“解锁后访问”的保守策略,保证数据处理的安全。 但是,在效率方面,处理封锁的机制会在数据库中产生额外的开销,增加发生死锁的机会,而且在只读事务中不会发生冲突,因此不需要使用锁,也不会在系统中发生死锁此外,并行性也会降低。 如果一个事务锁定了一行中的数据,则其他事务必须等待该事务完成,然后才能处理该行中的数据
乐观的控件认为事务之间的数据冲突(datarace )概率相对较低,因此尽可能按原样执行,在提交之前不锁定,因此不会发生锁定或死锁。 但是,如果这样做很简单,则可能会出现意外的结果,如两个事务读取、修改数据库中的行,然后将其写回数据库。
建议:用户同时使用量少的APP应用场景,采用乐观锁定方式。 如果对数据一致性的要求很高,则可以以牺牲性能为代价采用悲观的锁定。 这两种方式的前提是采用MySQL的解决方案。