1 ) 概念
Myisam
引擎: 只支持表锁,不支持行锁
InnoDB
引擎: 支持行锁和表锁
mysql 按照类型分,可分为 排它锁 和 共享锁
先创建一张表
create table `L1`(
`id` int(11) not null auto_increment,
`name` varchar(255) default null,
`count` int(11) default null,
primary key (`id`)
) engine=innodb default charset=utf8;
在这张表中操作 insert 很多数据,这里就不做操作了
1 ) 排它锁
主要语法 for update
, 示例
begin; -- 或 start transaction;
select * from L1 where name='wang' for update; -- 注意,这里name不是索引,使用表锁
commit; -- 事务结束,锁释放
begin;
select * from L1 where id=1 for update; -- 注意,这里id是索引,使用行锁
commit;
如果事务不结束,其他人操作,都会受到阻塞,进行不下去
需要等到本人commit之后,才能结束锁,其他人才能继续
应用场景
update goods set count=count-1 where id=3
sql操作示例
begin;
select count from goods where id=3 for update;
-- 获取个数进行判断
if 个数 > 0:
update goods set count=count-1 where id=3;
else:
-- 抢光了的处理
commit;
py操作
import pymysql
import threading
def task():
# 建立连接
conn = pymysql.connect(host='xxx.xxx.xxx.xxx', port=3306, user='root', password='xxxx', charset='utf8', db='userdb');
# 限定结果格式,如下面的 fetchone 后,是这样的格式: { id: 1, age: 10 }
# 如果是 fetchall, 则是这样的格式 ({ id: 1, age: 10 }, { id: 2, age: 11 })
cursor = conn.cursor(pymysql.cursors.DictCursor)
conn.begin() # 开启事务
cursor.execute('select id, age from tran where id=2 for update') # 排它锁
result = cursor.fetchone()
current_age = result['age']
if current_age > 0:
cursor.execute('update tran set age==age-1 where id=2')
else:
print('已售完')
conn.commit()
cursor.close()
conn.close()
def run():
# 创建5个线程, 都去执行 task
for i in range(5):
t = threading.Thread(target=task)
t.start()
if __name__ == '__main__':
run()
2 ) 共享锁
主要语法是: lock in share mode
sql 用法示例
begin;
select * from L1 where name='xxx' lock in share mode; -- name列不是索引,使用表锁
commit;
begin;
select * from L1 where id=1 lock in share mode; -- id列是索引 (行锁)
commit;
和排它锁的区别是: 加锁之后,其他可读,不可写
场景举例
sql 实现
begin;
select * from B where id=1 lock in share mode; -- id列是索引 (行锁)
insert into A(name) values('wang');
commit;