数据库表中非主键字段自动加1功能

Posted tommaoxiaoqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库表中非主键字段自动加1功能相关的知识,希望对你有一定的参考价值。

数据库版本表t_version包含的字段:

技术图片

 

用户创建config,在一个config下创建多个版本。 

在创建版本时,versionId字段要在该config下上一个版本ID的基础上自动加1.

 

在创建版本时,使用@Transaction注解设置数据库事务。

技术图片

 

 获取当前config的最大版本号

技术图片

 

 

此时存在的问题:用户A在获取到当前最大版本后,用户B同时也获取了当前最大版本 值与A相同,A创建版本,B再创建版本。就会存在两个相同的versionId。

 

思路1:

了解了数据库的隔离级别:

1.Read Uncommitted:可以读到未提交的数据。脏读:读到了其他人未提交的数据。

2.Read Committed:只能读到已提交的数据。第一次读5,其他人改成了4,再读是4。不可重复读:同一个字段两次不同值。

3.Repeated Read:第一次读5,其他人改成了4,再读还是5。mysql默认级别。   幻读:读到了新增条目。

4.Serializable:串行。事务一个个排队执行。

 

尝试将隔离级别设为最严格的串行: 

@Transactional(isolation = Isolation.SERIALIZABLE)

 

此时问题:出现死锁。

原因:

用户A获得了configId = 1的读锁A。
而在同时,B获得configId = 1的读锁B。
创建时,A尝试获得configId = 1的写锁,这个时候,由于configId = 1处不仅有事务A的读锁,还有事务B的读锁,因此事务A的update操作获取锁被阻塞。
此时,当事务B继续执行update操作时,由于事务A又拥有configId = 1的读锁A,因此进入互相等待状态,造成死锁。

参考:https://blog.csdn.net/weixin_38553453/article/details/83037979

项目中不能用事务的串行级别。

 

思路2:读取数据库值的时候采用 select for update 来读。

 

思路3:使用联合索引。采用该方式。

技术图片

 

 同一个configId它的VersionId不能相同。保证唯一性。

 

以上是关于数据库表中非主键字段自动加1功能的主要内容,如果未能解决你的问题,请参考以下文章

如何让mysql的自动递增的字段重新从1开始

三范式

结合实际应用总结mySql语句关键场景用法

SQL server中某个表的字段值为啥不能修改?

sqlserver字段如何自动更新

如何才能让mysql自动递增的字段重新从1开始呢