|
版本: |
|
小版本号: |
|
|
|
数据库: |
|
服务器操作系统: |
|
应用服务器: |
|
客户端操作系统: |
|
浏览器: |
|
|
|
安装了反编译工具,一步小心看到了官方的BizUtils.getNextSequence函数的源码,再此附上给大家分析(闭源的东西其实问题最多)
- public static int getNextSequence(String paramString)
- {
- String str1 = "update SA_KVSEQUENCE set k='" + paramString + "' where k='" + paramString + "' and $clientFilter(NULL)";
- String str2;
- if (updateKey(str1) > 0)
- {
- str2 = "update SA_KVSEQUENCE set v=v+1 where k='" + paramString + "' and $clientFilter(NULL)";
- if (updateKey(str2) > 0) {
- return getCurrentSequence(paramString);
- }
- }
- else
- {
- str2 = "insert into SA_KVSEQUENCE (k, v, $clientName) values('" + paramString + "', 1, $clientValue)";
- if (updateKey(str2) > 0) {
- return 1;
- }
- }
- throw BizSystemException.create("JUSTEP180317", new Object[] { paramString });
- }
-
- private static int updateKey(String paramString)
- {
- Connection localConnection = null;
- Statement localStatement = null;
- try
- {
- localConnection = ModelUtils.getConnectionInTransaction("/system/data");
- localStatement = localConnection.createStatement();
- int i = localStatement.executeUpdate(paramString);
- return i;
- }
- catch (Exception localException1)
- {
- throw BizSystemException.create(localException1, "JUSTEP180318", new Object[] { paramString });
- }
- finally
- {
- try
- {
- if (localStatement != null) {
- localStatement.close();
- }
- }
- catch (Exception localException2) {}
- try
- {
- if (localConnection != null) {
- localConnection.close();
- }
- }
- catch (Exception localException3) {}
- }
- }
-
- public static int getCurrentSequence(String paramString)
- {
- String str = "select v from SA_KVSEQUENCE where k='" + paramString + "' and $clientFilter(NULL)";
- Connection localConnection = null;
- Statement localStatement = null;
- try
- {
- localConnection = ModelUtils.getConnection("/system/data");
- localStatement = localConnection.createStatement();
- ResultSet localResultSet = localStatement.executeQuery(str);
- if (localResultSet.next())
- {
- i = localResultSet.getInt("v");
- return i;
- }
- int i = 0;
- return i;
- }
- catch (NamingException localNamingException)
- {
- throw new ModelException(localNamingException.getMessage(), localNamingException);
- }
- catch (SQLException localSQLException)
- {
- throw new ModelException(localSQLException.getMessage(), localSQLException);
- }
- finally
- {
- try
- {
- if (localStatement != null) {
- localStatement.close();
- }
- }
- catch (Exception localException1) {}
- try
- {
- if (localConnection != null) {
- localConnection.close();
- }
- }
- catch (Exception localException2) {}
- }
- }
复制代码
这里贴了4个函数,因为它们之间有相互的调用关系。显然如果发生高并发,这里的执行将可能出现问题,分析如下:
1、如果localConnection变量得到的连接是含事务的,且事务不会关闭,那么这个获取序号的操作将锁死数据库的那条记录,导致同类操作被阻塞,无法并发。
2、如果localConnection变量得到的连接不含事务,那么由于序号是在更新执行后才查询获取的这就可能导致同时被多个请求更新,最后得到了相同的序号。
|
|