如何处理大量数据并发操作

文件缓存,数据库缓存,优化sql,数据分流,数据库表的横向和纵向划分,使用协程处理并发,优化代码结构,使用协程处理并发!

锁的概概

一. 为什么要引入锁

多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:
丢失更新
A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统
脏读
A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致
不可重复读
A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致
并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做某些操作以避免产生数据不一致

二. Mysql中的锁

1.锁分类

  1. 按操作划分:DML锁,DDL锁
  2. 按锁的粒度划分:表级锁、行级锁、页级锁
  3. 按锁级别划分:共享锁、排他锁
  4. 按加锁方式划分:自动锁、显示锁
  5. 按使用方式划分:乐观锁、悲观锁

2. 乐观锁实现方法

  1. 每次获取商品时,不对该商品加锁。
  2. 在更新数据的时候需要比较程序中的库存量与数据库中的库存量是否相等,如果相等则进行更新
  3. 反之程序重新获取库存量,再次进行比较,直到两个库存量的数值相等才进行数据更新。
1
2
3
4
5
6
7
8
9
10
#### 乐观锁实现加一操作代码
# 我们可以看到,只有当对数量-1操作时才会加锁,只有当程序中值和数据库中的值相等时才正真执行。
'''
//不加锁
select id,name,stock where id=1;
//业务处理
begin;
update shop set stock=stock-1 where id=1 and stock=stock;
commit;
'''

3.悲观锁

  1. 每次获取商品时,对该商品加排他锁。
  2. 也就是在用户A获取获取 id=1 的商品信息时对该行记录加锁,期间其他用户阻塞等待访问该记录。
1
2
3
4
5
6
7
8
#### 悲观锁实现加一操作代码
# 我们可以看到,首先通过begin开启一个事物,在获得shop信息和修改数据的整个过程中都对数据加锁,保证了数据的一致性。
'''
begin;
select id,name,stock as old_stock from shop where id=1 for update;
update shop set stock=stock-1 where id=1 and stock=old_stock;
commit
'''

4.排它锁

  1. 排它锁又叫写锁,如果事务T对A加上排它锁,则其它事务都不能对A加任何类型的锁。获准排它锁的事务既能读数据,又能写数据。
  2. 用法 : SELECT _ FOR_UPDATE

5.共享锁(share lock)

  1. 共享锁又叫读锁,如果事务T对A加上共享锁,则其它事务只能对A再加共享锁,不能加其它锁。
  2. 获准共享锁的事务只能读数据,不能写数据。
  3. 用法: SELECT … LOCK IN SHARE MODE;