行锁
select amount from tbl_account where customer_id = '1' for update;
页锁
select amount from tbl_account where customer_id in ('1','2') for update;
表锁
select amount from tbl_account for update;
小结
本质上都是写锁(悲观锁)
读锁/共享锁
数据库新建一个查询表示第一个线程
start transaction;
-- 加共享锁(读锁)
select amount from tbl_account where customer_id = '1' lock in share mode;
数据库新建另一个查询表示第二个线程
-- 加了读锁可以执行查询,可以再加一个读锁
select amount from tbl_account where customer_id = '1';
select amount from tbl_account where customer_id = '1' lock in share mode;
-- 加了读锁不可以加写锁
select amount from tbl_account where customer_id = '1' for update;
等到一个线程中的读锁释放后,第二个线程可以加写锁
commit;
写锁/悲观锁
数据库新建一个查询表示第一个线程
start transaction;
-- 加共享锁(读锁)
select amount from tbl_account where customer_id = '1' for update;
数据库新建另一个查询表示第二个线程
-- 加了写锁可以执行
select amount from tbl_account where customer_id = '1';
--加了写锁以下不可以执行
select amount from tbl_account where customer_id = '1' lock in share mode;
select amount from tbl_account where customer_id = '1' for update;
都必须等到第一个线程写锁释放才能执行
commit;
小结
同一个线程里加写锁,读锁都不受限制,可以加无数个。
以上锁都是悲观锁,依赖数据库的机制。特别是分布式下,用java中的锁失效。写多读少,保证数据安全。
乐观锁
update goods set amount = amount-#{buy},version=version+1 where name = #{name} and version = #{version} (版本号控制)
update goods set amount = amount-#{buy},version=version+1 where name = #{name} and amount-#{buy} >=0 (状态控制)
以上两种适用于抢购。
CAS机制
利用watch指令在redis事务中提供CAS能力。
1.2.4版本memcached的gets和cas实现
随机休眠毫米,为了错峰,防止栈溢出