共享锁:又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据能够共享一把锁,都能访问到数据,可是只能读不能修改。mysql
排他锁:又称为写锁,简称X锁,顾名思义,排他锁就是不能与其余所并存,如一个事务获取了一个数据行的排他锁,其余事务就不能再获取该行的其余锁,包括共享锁和排他锁,可是获取排他锁的事务是能够对数据就行读取和修改。sql
mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,blog
若是加排他锁能够使用select ...for update语句,加共享锁能够使用select ... lock in share mode语句。索引
因此加过排他锁的数据行在其余事务种是不能修改数据的,也不能经过for update和lock in share mode锁的方式查询数据,事务
但能够直接经过select ...from...查询数据,由于普通查询没有任何锁机制。get
begin; select * from goods where id = 1 for update; update goods set stock = stock - 1 where id = 1; commit;
表锁和行锁it
InnoDB行锁是经过给索引上的索引项加锁来实现的,只有经过索引条件检索数据,InnoDB才使用行级锁,不然,InnoDB将使用表锁。class
悲观锁:date
/* 更新库存(使用悲观锁) * @param productId * @return */ public boolean updateStock(Long productId){ //先锁定商品库存记录 ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId} FOR UPDATE", productId); if (product.getNumber() > 0) { int updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId}", productId); if(updateCnt > 0){ //更新库存成功 return true; } } return false; }
乐观锁:select
/** * 下单减库存 * @param productId * @return */ public boolean updateStock(Long productId){ int updateCnt = 0; while (updateCnt == 0) { ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId}", productId); if (product.getNumber() > 0) { updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId} AND number=#{number}", productId, product.getNumber()); if(updateCnt > 0){ //更新库存成功 return true; } } else { //卖完啦 return false; } } return false; }