mysql批量插入語句執行失敗的話,是部分失敗還是全部失敗


 一、前言

下面簡單介紹下背景,如果看着覺得繞,直接跳到第二章。

項目開發中,正好遇到這個問題。

將一批從外部第三方接口獲取到的數據存儲到本地mysql數據庫,假設接口返回的數據類型為A,經過A到B的轉換規則轉換后,

要插入數據庫的數據類型為B。那么在A獲取到1000條記錄,轉換為1000條B記錄,用mybatis的批量插入語句。

要保證批量插入是否成功的話,就要考慮如果因為部分記錄已經存在於數據庫的話,批量插入語句是否會全部失敗還是部分失敗。(比如有唯一索引,那么是違反了唯一約束的失敗呢,還是整個批量語句全失敗)。

如果是全失敗,就可以在1000條A轉換為B的時候,先查詢記錄是否存在,存在則不進行轉換,因為轉換了的話,最后會導致批量語句失敗。

如果是部分失敗,就可以全轉換,不用考慮本地數據庫唯一索引的問題。

 

二、測試

表結構,主要包括自增主鍵、日期(日期上會建立唯一索引,保證同一天的只會有一條記錄),其他字段都不重要:

CREATE TABLE `biz_riskfree_interest_rate` (
  `id` bigint(32) NOT NULL AUTO_INCREMENT,
  `rate_date` char(10) COLLATE utf8_unicode_ci DEFAULT NULL,
  `period_span` char(3) COLLATE utf8_unicode_ci DEFAULT NULL,
  `rate` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq` (`rate_date`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

 

索引如下:(有一個唯一索引,字段為rate_date)

 

已經存在的數據如下:

 

 好了,開始測試:

1.如果批量語句為插入2017年7月5號和207年7月6號,預期會成功,因為原始數據里只存了到2017年7月4日的數據,不會違反唯一索引:

insert into `biz_riskfree_interest_rate` (`rate_date`, `period_span`, `rate`) values('20170705','1y','3.4596'),('20170706','1y','3.4596');

 

可以看到,成功了,沒問題,數據已經插入進去了。

 

2.如果批量語句為插入2017年7月6號和2017年7月7號:(預期6號會失敗,因為上面已經插入了6號的數據,唯一性檢查會失敗。但是7號應該成功,所以結果會不會是6號失敗,7號成功呢?)

INSERT INTO `biz_riskfree_interest_rate` (`rate_date`, `period_span`, `rate`) VALUES('20170706','1y','3.4596'),('20170707','1y','3.4596');

 

結果是:都失敗了,因為並沒有查出來“'20170707'”這天的數據。

 

3.上面失敗了,和順序有沒有關系呢,如果7號放在前面,6號放后面執行呢?

INSERT INTO `biz_riskfree_interest_rate` (`rate_date`, `period_span`, `rate`) VALUES('20170707','1y','3.4596'),('20170706','1y','3.4596');

 

 

 依然失敗了。

結論:批量語句,只要有一個失敗,就會全部失敗。開發程序的時候要注意這點。

 

三、結論

批量語句,只要有一個失敗,就會全部失敗。總之,是原子的,大家可以自己試試。

值得注意的是,以上都是在沒有手動開啟事務的情況下操作的,但這依然是一個原子操作。 大家也可以手動開啟事務試試(先執行begin語句,再執行上述命令即可)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM