$ kubectl create -f pvc2.yaml persistentvolumeclaim/pvc-sfs-auto-example created
$ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-sfs-auto-example Bound pvc-1f1c1812-f85f-41a6-a3b4-785d21063ff3 10Gi RWX csi-nas 29s
$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-1f1c1812-f85f-41a6-a3b4-785d21063ff3 10Gi RWO Delete Bound default/pvc-sfs-auto-example csi-nas 20s
UPDATE goods SET available = available -1WHERE id = xxx
如果是这么简单的话,那就没有必要讨论了。实际上在并发请求的业务场景下,有可能出现 available 变量变成负数。
虽然我们可以将 available 变量设计成 int unsigned 字段来避免,但是在不同的 MySQL 版本下,会出现 available 溢出成为一个非常大的数。
解决方法
悲观锁的方案:SELECT FOR UPDATE
当我们查询 goods 信息后就把当前的数据锁定,直到我们修改完毕后再解锁。不过 FOR UPDATE 仅适用于 InnoDB,且必须在事务区块中才能生效。
1 2 3 4 5 6 7 8 9
set autocommit = 0; // 设置MySQL为非autocommit模式: begin trans;// 开始事务 select avaliable from goods where id = xxx for update; //1.查询出商品信息 if (avaliable >= 0) { affectNum = udpate goods set available = available - 1 where id = xx ; commit ; // 4.提交事务 } else { rollback ; }
乐观锁假设数据一般情况下不会冲突,在数据提交更新的时候,才会对检测数据的冲突与,如果发现冲突了,则让返回用户错误的信息,让用户决定。 通常做法是记录加一个 Version 字段。读取记录时,连同 Version 一同读出。数据每次更新时候,Version + 1, 更新时判断记录的当前版本与之前取出来的 Version 值比对, 如果当前版本号与第一次取出来的 Version 值相等,则予以更新,否则认为是过期数据。
1 2 3 4
select avaiable ,version from goods where id=xxx limit 1; // 查询version if (available >0) { update goods set avaiable=avaiable-1where id =xx and version=<刚查出来的 Version>; }
弊端: 这样虽然保证安全,但是需要执行2次 SQL
Update 时增加 available 查询条件
1
udpate goods set available = available -1where id = xx and available -1>=0 ;
Innodb 的 Update 语句,对于 id 是主键索引的情况下会执行行锁。该语句在 MySQL中是先读后更新,串行且原子的。单条语句,实际上也是一个事务。这个方法效率更快,且安全。
auto descriptor = obj.GetDescriptor(); auto reflection = obj.GetReflection(); // 通过 FieldName 获取字段 auto idField = descriptor->FindFieldByName("age"); reflection->SetInt32(&obj, idField, 18); for (unsigned int i = 0; i < descriptor->field_count(); ++i) { auto field = descriptor->field(i);