252 阅读1分钟

行锁

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实现

随机休眠毫米,为了错峰,防止栈溢出