中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Mysql數據庫數據更新失效的原因和解決方法

發布時間:2020-06-12 12:20:09 來源:億速云 閱讀:4394 作者:Leah 欄目:MySQL數據庫

這篇文章將為大家詳細講解有關Mysql數據庫數據更新失效的原因和解決方法,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

1. 背景

最近的項目中遇到一項問題,并發更新某一單據的時候,出現了更新失效的情況。比如:

@Transactional(rollbackFor = Exception.class)
public void update(Integer id){
    //1.按id查詢
    //2.更新某一字段的值
}

生成的SQL大概是這樣的:

UPDATE  table 
SET field = #{field,jdbcType=INTEGER}
WHERE id= 1

那么以上代碼產生的問題就是:
對于同一個id=1來說,請求A與請求B都進到了update方法中,此時按id查詢得到的信息是相同的,那么請求A更新了id=1的這條記錄之后,此時,請求B又對id=1的記錄進行更新,此時注意請求B更新id=1的記錄的時候,請求B按id查詢到的數據已經是舊數據了,請求B執行完之后,請求A的更新被請求B覆蓋了。

如果更新的是狀態,那倒無所謂,如果庫存量呢?
如果更新的是庫存,是在這條記錄的原始值上進行+或者-操作,是不是就出問題了?

2. 分析產生的原因

事后寫了個小demo來復現問題,代碼大致如下:

需求: 某個分類每被訪問一次,排序就+1;
開啟兩個客戶端同時訪問

@Transactional(rollbackFor = Exception.class)
public void updateStatusTest(Integer id) {
    System.out.println("start:"+Thread.currentThread().getName());
    Category category = categoryMapper.selectById(id);
    try {
        Thread.sleep(8000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+":"+category);
    category.setSort(category.getSort()+1);
    categoryMapper.updateById(category);

    category = categoryMapper.selectById(id);
    System.out.println(Thread.currentThread().getName()+":"+category);
    System.out.println("end:"+Thread.currentThread().getName());
}

DAO層使用的mybatis,生成日志大致如下:
需要更新的sort值數據庫初始為:0

start:http-nio-8062-exec-1
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@2d5c951c] will be managed by Spring
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 0, 1111
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
 Time:27 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
        parent_id,
        image_url,
        icon_url,
        sort,
        status 
    FROM
        t_admin_category 
    WHERE
        cid=6

start:http-nio-8062-exec-2
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@700c5b36] will be managed by Spring
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
 Time:2 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
        parent_id,
        image_url,
        icon_url,
        sort,
        status 
    FROM
        t_admin_category 
    WHERE
        cid=6

==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 0, 1111
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046]
http-nio-8062-exec-1:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=0, status='1111'}
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9] from current transaction
==>  Preparing: UPDATE t_admin_category SET category_name=?, parent_id=?, image_url=?, icon_url=?, sort=?, status=? WHERE cid=? 
==> Parameters: 1(String), 0(Integer), 11111(String), 1(String), 1(Integer), 1111(String), 6(Integer)
 Time:16 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.updateById
Execute SQL:
    UPDATE
        t_admin_category 
    SET
        category_name='1',
        parent_id=0,
        image_url='11111',
        icon_url='1',
        sort=1,
        status='1111' 
    WHERE
<==    Updates: 1
        cid=6

Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9] from current transaction
    SELECT
        cid,
        category_name,
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
        parent_id,
==> Parameters: 6(Integer)
        image_url,
        icon_url,
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
        sort,
        status 
<==        Row: 6, 1, 0, 11111, 1, 1, 1111
    FROM
<==      Total: 1
        t_admin_category 
    WHERE
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
        cid=6

http-nio-8062-exec-1:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=1, status='1111'}
end:http-nio-8062-exec-1
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6df7e3e9]
http-nio-8062-exec-2:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=0, status='1111'}
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046] from current transaction
==>  Preparing: UPDATE t_admin_category SET category_name=?, parent_id=?, image_url=?, icon_url=?, sort=?, status=? WHERE cid=? 
 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.updateById
Execute SQL:
    UPDATE
        t_admin_category 
    SET
        category_name='1',
        parent_id=0,
        image_url='11111',
        icon_url='1',
        sort=1,
        status='1111' 
    WHERE
        cid=6

==> Parameters: 1(String), 0(Integer), 11111(String), 1(String), 1(Integer), 1111(String), 6(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046] from current transaction
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 0, 1111
 Time:16 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
<==      Total: 1
        parent_id,
        image_url,
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7af43046]
        icon_url,
        sort,
        status 
    FROM
http-nio-8062-exec-2:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=0, status='1111'}
        t_admin_category 
end:http-nio-8062-exec-2
    WHERE
        cid=6

大致意思:
請求A與請求B,同時操作id=6的這條記錄時,查詢出來id=6的這條記錄,然后請求A對其進行了修改 SET sort=1操作,完事之后,請求A的事務提交了。而此時請求B,通過id=6條件查詢到的category的信息是請求A提交之前的,此時請求B執行了SET sort=1,覆蓋了請求B的修改操作。

3. 解決思路

解決方法其它很簡單,我們上面可以看到,update語句是直接set sort=1的,我們只需要改為set sort = sort +1 就可以了。你不信?那我改一下試試:

@Transactional(rollbackFor = Exception.class)
public void updateStatusTest(Integer id) {
    System.out.println("start:"+Thread.currentThread().getName());
    Category category = categoryMapper.selectById(id);
    try {
        Thread.sleep(8000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+":"+category);
//        category.setSort(category.getSort()+1);
    categoryMapper.updateStatusById(category);

    category = categoryMapper.selectById(id);
    System.out.println(Thread.currentThread().getName()+":"+category);
    System.out.println("end:"+Thread.currentThread().getName());
}

Mapper文件:

<update id="updateStatusById" parameterType="com.sxl.simple.shop.admin.category.entity.Category">
      UPDATE
        t_admin_category
      SET
        sort =sort + 1
    WHERE
        cid= #{cid,jdbcType=INTEGER}
</update>

我們執行試一下,看下日志:

start:http-nio-8062-exec-1
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@6c17839b] will be managed by Spring
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 0, 1111
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
 Time:43 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
        parent_id,
        image_url,
        icon_url,
        sort,
        status 
    FROM
        t_admin_category 
    WHERE
        cid=6

start:http-nio-8062-exec-2
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@195f8b5a] will be managed by Spring
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 0, 1111
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022]
 Time:2 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
        parent_id,
        image_url,
        icon_url,
        sort,
        status 
    FROM
        t_admin_category 
    WHERE
        cid=6

http-nio-8062-exec-1:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=0, status='1111'}
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f] from current transaction
==>  Preparing: UPDATE t_admin_category SET sort =sort + 1 WHERE cid= ? 
==> Parameters: 6(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f] from current transaction
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.updateStatusById
Execute SQL:
    UPDATE
        t_admin_category 
    SET
        sort =sort + 1 
    WHERE
        cid= 6

==> Parameters: 6(Integer)
 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
Execute SQL:
<==        Row: 6, 1, 0, 11111, 1, 1, 1111
    SELECT
<==      Total: 1
        cid,
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
        category_name,
        parent_id,
http-nio-8062-exec-1:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=1, status='1111'}
        image_url,
end:http-nio-8062-exec-1
        icon_url,
        sort,
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
        status 
    FROM
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
        t_admin_category 
    WHERE
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e925f3f]
        cid=6

 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.updateStatusById
Execute SQL:
    UPDATE
        t_admin_category 
    SET
        sort =sort + 1 
    WHERE
        cid= 6

 Time:0 ms - ID:com.sxl.simple.shop.admin.category.mapper.CategoryMapper.selectById
Execute SQL:
    SELECT
        cid,
        category_name,
        parent_id,
        image_url,
        icon_url,
        sort,
        status 
    FROM
        t_admin_category 
    WHERE
        cid=6

http-nio-8062-exec-2:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=0, status='1111'}
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022] from current transaction
==>  Preparing: UPDATE t_admin_category SET sort =sort + 1 WHERE cid= ? 
==> Parameters: 6(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022] from current transaction
==>  Preparing: SELECT cid,category_name,parent_id,image_url,icon_url,sort,status FROM t_admin_category WHERE cid=? 
==> Parameters: 6(Integer)
<==    Columns: cid, category_name, parent_id, image_url, icon_url, sort, status
<==        Row: 6, 1, 0, 11111, 1, 2, 1111
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c88f022]
http-nio-8062-exec-2:Category{cid=6, categoryName='1', parentId=0, imageUrl='11111', iconUrl='1', sort=2, status='1111'}
end:http-nio-8062-exec-2

看完上述內容,你們對Mysql數據庫數據更新失效的原因和解決方法大概了解了嗎?如果想了解更多相關文章內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大厂| 闽侯县| 于都县| 淮安市| 汉源县| 二手房| 汉寿县| 洞头县| 泊头市| 五华县| 宁波市| 南投市| 吉安县| 涿州市| 江西省| 营山县| 宁夏| 司法| 阿拉善盟| 锦屏县| 阿拉尔市| 苏尼特左旗| 清新县| 连州市| 六盘水市| 黄陵县| 哈巴河县| 朔州市| 龙胜| 柳林县| 永平县| 彭水| 长沙县| 延津县| 洞头县| 金秀| 崇仁县| 英吉沙县| 花垣县| 海门市| 元朗区|