Remember a production fault troubleshooting

Trouble phenomenon:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

Check the database data, there are two data that meet the conditions.

There are declarative transactions in the method, and the specific logic of the colleague's code is as follows:

1. Conditionally query the xxx_deploy table, and return if the result is not empty;

2. The result is empty, trylock, valid time 3s;

3. The lock is successful, and the conditions query the xxx_deploy table;

4. The result is not empty, unlock and return;

5. The result is empty, and the object is assembled according to the conditions;

6 Insert a record in the xxx_deploy table, unlock and return the object;

7. The lock is unsuccessful, and the while loop condition queries the xxx_deploy table until the returned result is not empty, return.

problem analysis:

In the multi-threaded scenario, thread A executes to step 6, inserts a record in the xxx_deploy table and unlocks it, and thread B immediately trieslock successfully. The result of the conditional query on the xxx_deploy table may be empty. This is because the method has added a transaction (for mybatis) In the same session), thread B and thread A are not in the same session, the query result of step 1 is cached in the session of thread B, and has not been updated by insert (insert operation occurs in the session of thread A, only update Thread A session), when the conditional query in step 3 is executed, because the conditions are the same, the cache is directly returned, and the returned result is still empty, and then the insert is executed, resulting in two pieces of data in the database.

to sum up:

The same session and select call> 1 time. If an update operation is inserted between two calls, the cache will be invalidated immediately. As long as there are insert, update and delete statements in the session, the cache in the session will be refreshed immediately. But note that this is only between the same session. Between different sessions, such as session1 and session2, insert/update/delete in session1 will not affect the cache under session 2, which will generate dirty data in high concurrency or distributed situations.

Guess you like

Origin blog.csdn.net/noob9527/article/details/115304699