商品信息快照
商城中,经常要对商品信息进行修改,这会影响到已存在的信息.
如何保证商品信息的修改不对已有信息影响呢?
常见方式就是快照
.
也就是一条商品记录的不同版本记录.
在数据库表中,我们对记录商品信息的记录增加个版本字段 version
,该字段有与没有并不影响结果,只是为了方便观察和历史追溯.
原始表数据:
如果在此时,我们想修改商品信息,比如改个名字,原来所执行的sql为:
update commodities set name = 'phone3' where id = 1;
但是因为想保存商品的快照,则需要执行如下的事务:
start transaction ;
select * from commodities where uuid = 'ESP20190102150405' order by id desc limit 1 for update ;
insert into commodities (id, uuid, name, unit_price, inventory, merchant_id, category_id, version)
values (null, 'ESP20190102150405', 'phone3', 233000, 111,1,1,1);
commit;
执行后的结果:
还有哪些不足呢?
回过头来继续思考.
由于此处的库存数据 inventory
字段是个共享数据,在每次进行快照操作时,都需要将其复制一份,会影响到在快照过程中,用户下单的操作.
所以可以单独将库存信息拎出来,放到独立的一张表中,通过外键将商品和库存关联,以避免在快照操作时影响下单的并发操作.
修改后的结果如下:
start transaction ;
// 该sql甚至可以不需要 for update 操作,减少一次加锁行为.
select * from commodities where uuid = 'ESP20190102150405' order by id desc limit 1 for update ;
insert into commodities (id, uuid, name, unit_price, merchant_id, category_id, version, inventory_id)
select null, uuid, name, unit_price, merchant_id, category_id, version+1, inventory_id
from commodities where uuid = 'ESP20190102150405' order by id desc limit 1;
commit;
如此即保留了商品信息的历史记录,也提高了并发性能.
再思考
如果我们想研究对商品某些信息的修改后,去化效果,那么将库存与商品分表则不适合了,因为我们仅保留了1个共享的库存数据,而没有保留历史不同版本的库存数据,这个时候,要么使用第一种设计方式,要么直接对订单进行统计.