成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 insert 配置 "SELECT LAST_INSERT_ID()" 返回個0呢?

開發(fā) 前端
很多類似這樣的技術(shù)問題,都是來自于小傅哥對源碼的學(xué)習(xí),最開始是遇到問題的時候去翻看源碼,雖然很多時候也很難把整個邏輯捋順,但一點點的積累確實會讓研發(fā)人員對技術(shù)有更加夯實的認(rèn)知。

一、前言:一個Bug

沒想到一個Bug,竟然搞我兩次!

我大抵是卷上癮了,橫豎都睡不著,坐起來身來打開Mac和外接顯示器,這Bug沒有由來,默然看著打印異常的屏幕,一個是我的,另外一個也是我的。

今天這個問題主要體現(xiàn)在大家平常用的Mybatis,在插入數(shù)據(jù)的時候,我們可以把庫表索引的返回值通過入?yún)ο蠓祷鼗貋?。但是通過我自己手寫的Mybatis,每次返回來的都是0,而不是最后插入庫表的索引值。因為是手寫的,不是直接使用Mybatis,所以我會從文件的解析、對象的映射、SQL的查詢、結(jié)果的封裝等一直排查下去,但竟然問題都不在這?!

圖片

  • 就是這個 selectKey 的配置,在執(zhí)行插入SQL后,開始執(zhí)行獲取最后的索引值。
  • 通常只要配置的沒問題,返回對象中也有對應(yīng)的 id 字段,那么就可以正確的拿到返回值了。PS:問題就出現(xiàn)在這里,小傅哥手寫的 Mybatis 竟然只難道返回一個0!

二、分析:診斷異常

可能大部分研發(fā)伙伴沒有閱讀過 Mybatis 源碼,所以可能不太清楚這里發(fā)生了什么,小傅哥這里給大家畫張圖,告訴你發(fā)生了什么才讓返回的結(jié)果為0的。

圖片

  • Mybatis 的處理過程可以分為兩個大部分來看,一部分是解析,另外一部分是使用。解析的時候把 Mapper XML 中的 insert 標(biāo)簽語句解析出來,同時解析 selectKey 標(biāo)簽。最終解析完成后,把解析的語句信息使用 MappedStatement 映射語句類存放起來。便于后續(xù)在 DefaultSqlSession 執(zhí)行操作的時候,可以從 Configuration 配置項中獲取出來使用。
  • 那么這里有一個非常重要的點,就是執(zhí)行 insert 插入的時候,里面還包含了一句查詢的操作。那也就是說,我們會在一次 Insert 中,包含兩條執(zhí)行語句。重點:bug就發(fā)生在這里,為什么呢?因為最開始這兩條語句執(zhí)行的時候,在獲取鏈接的時候,每一條都是獲取一個新的鏈接,那么也就是說,insert xxx、select LAST_INSERT_ID() 在兩個 connection 連接執(zhí)行時,其實是不對的,沒法獲取到插入后的索引 ID,只有在一個鏈接或者一個事務(wù)下(一次 commit)才能有事務(wù)的特性,獲取插入數(shù)據(jù)后的自增ID。
  • 而因為這部分最開始手寫 JdbcTransaction 實現(xiàn) Transaction 接口獲取連接的時候,每一次都是新的鏈接,代碼塊如下;

圖片

  • 這里的鏈接獲取,最開始沒有 if null 的判斷,每次都是直接獲取鏈接,所以這種非一個鏈接下的兩條 SQL 操作,所以必然不會獲得到正確的結(jié)果,相當(dāng)于只是單獨執(zhí)行SELECT LAST_INSERT_ID() 所以最終的查詢結(jié)果為 0 了就!你可以測試把這條語句復(fù)制到 SQL查詢工具中執(zhí)行

三、震驚:同一個坑

但其實就這么一個鏈接的問題,在小傅哥手寫Spring中也同樣遇到過。

圖片

在 Spring 中有一部分是關(guān)于事務(wù)的處理,其實這些事務(wù)的操作也是對 JDBC 的包裝操作,依賴于數(shù)據(jù)源獲得的鏈接來管理事務(wù)。而我們通常使用 Spring 也是結(jié)合著 Mybatis 配置上數(shù)據(jù)源的方式進(jìn)行使用,那么在一個事務(wù)下操作多個 SQL 語句的時候,是怎么獲得同一個鏈接的呢。因為從上面????的案例中,我們得知保證事務(wù)的特性,需要在同一個鏈接下,即使是操作多條SQL

由于多個SQL的操作,已經(jīng)是相當(dāng)于每次都獲取一個新的 Session 有一個新的鏈接從連接池中獲得,但為了能達(dá)到事務(wù)的特性,所以在需要有事務(wù)操作下的多個 SQL 前需要開啟事務(wù)操作,無論是手動還是注解。

而這個事務(wù)的開啟動作處理做一些事務(wù)傳播行為和隔離級別的限制,其實更重要的是讓多個 SQL 的執(zhí)行獲取的鏈接,需要是同一個。所以這里就引入了 ThreadLocal 基于它在同一個線程操作下保存信息的同步特性,其實這里的從事務(wù)下獲取的鏈接,其實就是保存到 TransactionSynchronizationManager#resources 屬性中的。

雖然就這么一小塊內(nèi)容,但在小傅哥最開始手寫Spring的時候,也是給漏下了。直到到測試的時候,才發(fā)現(xiàn)鏈接發(fā)現(xiàn)事務(wù)總是不成功,最初還以為是整個切面邏輯沒有切進(jìn)去或者是我的操作方式有誤。直到逐步排查調(diào)試代碼,發(fā)現(xiàn)原來多個SQL的執(zhí)行竟然不是獲得的同一個鏈接,所以也就沒法讓事務(wù)生效。

四、常見:事務(wù)失效

可能就是這么一個小小的鏈接問題,有時候就會引起一堆的異常,如果說我們沒有學(xué)習(xí)過源碼,那么可能也不知道這樣的問題到底是如何發(fā)生的。所以往往深入的研究和探索,才能讓你解釋一個問題的時候,更加簡單直接。

那么你說,事務(wù)失效的原因還有哪些?- 分享一些常見,如果你還有遇到其他的,可以發(fā)到評論區(qū)一起看看。

  • 數(shù)據(jù)庫引擎不支持事務(wù):這里以 MySQL 為例,其 MyISAM 引擎是不支持事務(wù)操作的,InnoDB 才是支持事務(wù)的引擎,一般要支持事務(wù)都會使用 InnoDB。https://dev.mysql.com/doc/refman/8.0/en/storage-en... 從 MySQL 5.5.5 開始的默認(rèn)存儲引擎是:InnoDB,之前默認(rèn)的都是:MyISAM,所以這點要值得注意,底層引擎不支持事務(wù)再怎么搞都是白搭。
  • 方法不是 public 的:來自 Spring 官方文檔【W(wǎng)hen using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.】@Transactional 只能用于 public 的方法上,否則事務(wù)不會失效,如果要用在非 public 方法上,可以開啟 AspectJ 代理模式。
  • 沒有被 Spring 管理:// @Service - 這里被注釋掉了 public class OrderServiceImpl implements OrderService { @Transactional public void placeOrder(Order order) { // ... } }。
  • 數(shù)據(jù)源沒有配置事務(wù)管理器:一般來自于自研的數(shù)據(jù)庫路由組件@Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
  • 異常被吞了。catch 后直接吃了,事務(wù)異常無法回滾。同時要配置上對應(yīng)的異常@Transactional(rollbackFor = Exception.class)

五、總結(jié):學(xué)習(xí)經(jīng)驗

很多類似這樣的技術(shù)問題,都是來自于小傅哥對源碼的學(xué)習(xí),最開始是遇到問題的時候去翻看源碼,雖然很多時候也很難把整個邏輯捋順,但一點點的積累確實會讓研發(fā)人員對技術(shù)有更加夯實的認(rèn)知。

那么在現(xiàn)在我之所以去手寫Spring、手寫Mybatis,也是希望通過把這樣的知識全部整理處理,從中學(xué)習(xí)復(fù)雜邏輯的設(shè)計方案、設(shè)計原則和如何運用設(shè)計模式解決復(fù)雜場景的問題。PS:通常我們的業(yè)務(wù)代碼復(fù)雜度很難到這個程度,所以在見過”天“后,以后所承接的業(yè)務(wù)就很容易做設(shè)計了。

另外就是對各類技術(shù)細(xì)節(jié)的把控,以及積累于這樣的經(jīng)驗把相關(guān)技術(shù)設(shè)計運用到一些類似 SpringBoot Starter 等的開發(fā),只有類似這樣的廣度、高度、深度,才能真的把個人的研發(fā)能力提升起來。

責(zé)任編輯:武曉燕 來源: bugstack蟲洞棧
相關(guān)推薦

2010-10-09 16:11:21

Mysql函數(shù)

2018-08-23 09:10:01

數(shù)據(jù)庫MySQLInnoDB

2018-08-27 07:29:34

InnoDBinsertselect

2010-09-03 15:27:02

SQLSELECT語句

2021-07-03 15:22:02

Mybatis InsID源碼

2010-09-13 10:55:44

SQL Server

2020-04-30 10:07:54

數(shù)據(jù)庫數(shù)據(jù)遷移Insert into

2010-04-16 14:26:14

bulk Insert

2024-03-06 08:18:22

語句GreatSQL

2024-04-10 14:27:03

MySQL數(shù)據(jù)庫

2011-07-22 16:59:30

MySQL數(shù)據(jù)庫嵌套查詢

2011-08-24 15:48:38

INSERT中文man

2024-07-05 10:19:59

2011-01-18 15:27:30

Postfix

2010-09-10 11:01:09

sql變量

2010-05-27 14:47:14

MySQL INSER

2010-10-08 14:32:47

MySQL使用INSE

2020-07-06 08:15:59

SQLSELECT優(yōu)化

2020-04-30 11:25:32

Insert into數(shù)據(jù)庫索引

2022-05-16 08:03:12

MySQL數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲区一区二区 | 不卡一二三区 | 在线第一页 | 在线精品一区二区 | 二区中文字幕 | 国产电影一区二区在线观看 | 成人免费网视频 | 日韩精品四区 | 伊人网影院 | 中文字幕 在线观看 | 亚洲精品日韩在线 | 成人免费观看视频 | av网站在线播放 | 欧美视频三区 | 草久免费视频 | 欧美一级片免费看 | 欧美精品成人一区二区三区四区 | 噜啊噜在线| 激情视频中文字幕 | 欧美日韩国产在线 | 国产精品日韩在线 | 五月花丁香婷婷 | 超碰精品在线 | 久久精品手机视频 | 男女免费在线观看视频 | 色呦呦在线| 色视频一区二区 | 精品国产一区二区三区av片 | 日韩免费视频 | 国产在线激情视频 | 日韩在线播放av | 免费观看www7722午夜电影 | 色综久久 | 欧美综合久久久 | 日韩中文字幕免费在线观看 | 精品久久久久久久久久久久久久 | 亚洲国产成人精品女人久久久 | 国产乱码一区 | 日日夜夜精品视频 | 99精品免费视频 | 97成人在线|