今天比較閑看到大家在群里討論關於數據庫操作的問題,其中談到了“事務”這個詞,坦白講雖然作為計算機專業的學生,在上學的時候確實知道存儲過程、觸發器、事務等等這些名詞的概念,但是由於畢業后從事的不是服務器方面的工作,對數據庫方面的知識一直停留在理論階段,在iOS中有兩種比較常用的數據庫,一種是sqlite,另外一種是coreData,這二者的優缺點在這里不再贅述,如有感興趣的同學可以查閱相關資料
令人興奮的是,當談到“事務”時,我想到了sqlite本身是支持事務操作的,FMDB作為sqlite的上層封裝也對事務進行了支持,那么說了這么多給不了解“事務”這個詞的同學解釋一下吧:通常一次 sqlite3_exec 就是一次事務,假如你要對數據庫中的Stutent表插入新數據,那么該事務的具體過程是:開始新事物->插入數據->提交事務,那么當我們要往該表內插入500條數據,如果按常規操作處理就要執行500次“開始新事物->插入數據->提交事務”的過程。
好吧,今天的重點來了,舉個例子:假如北京的一家A工廠接了上海一家B公司的500件產品的訂單,思考一下:A工廠是生產完一件立即就送到B公司還是將500件產品全部生產完成后再送往B公司?答案肯定是后者,因為前者浪費了大量的時間、人力物力花費在往返於北京和上海之間。同樣這個道理也能用在我們的數據庫操作上,下面是我自己對使用事務和不使用事務的兩種測試:
測試代碼:
下面代碼中總共調用了三次插入數據的方法,由於第一次調用過程中包含數據庫和表的創建等一系列過程,因此第二三次調用插入方法計算出的時間才是准確的。(數據庫采用FMDB)
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [[TestDataBase sharedInstanceDB] insertData:0 useTransaction:NO]; NSDate *date1 = [NSDate date]; [[TestDataBase sharedInstanceDB] insertData:500 useTransaction:NO]; NSDate *date2 = [NSDate date]; NSTimeInterval a = [date2 timeIntervalSince1970] - [date1 timeIntervalSince1970]; NSLog(@"不使用事務插入500條數據用時%.3f秒",a); [[TestDataBase sharedInstanceDB] insertData:1000 useTransaction:YES]; NSDate *date3 = [NSDate date]; NSTimeInterval b = [date3 timeIntervalSince1970] - [date2 timeIntervalSince1970]; NSLog(@"使用事務插入500條數據用時%.3f秒",b); }
下面是具體的插入實現方法,
useTransaction為真代表使用事務處理,反之不使用
- (void)insertData:(int)fromIndex useTransaction:(BOOL)useTransaction { [_dataBase open]; if (useTransaction) { [_dataBase beginTransaction]; BOOL isRollBack = NO; @try { for (int i = fromIndex; i<500+fromIndex; i++) { NSString *nId = [NSString stringWithFormat:@"%d",i]; NSString *strName = [[NSString alloc] initWithFormat:@"student_%d",i]; NSString *sql = @"INSERT INTO Student (id,student_name) VALUES (?,?)"; BOOL a = [_dataBase executeUpdate:sql,nId,strName]; if (!a) { NSLog(@"插入失敗1"); } } } @catch (NSException *exception) { isRollBack = YES; [_dataBase rollback]; } @finally { if (!isRollBack) { [_dataBase commit]; } } }else{ for (int i = fromIndex; i<500+fromIndex; i++) { NSString *nId = [NSString stringWithFormat:@"%d",i]; NSString *strName = [[NSString alloc] initWithFormat:@"student_%d",i]; NSString *sql = @"INSERT INTO Student (id,student_name) VALUES (?,?)"; BOOL a = [_dataBase executeUpdate:sql,nId,strName]; if (!a) { NSLog(@"插入失敗2"); } } } [_dataBase close]; }
最后將兩種方式的耗時進行對比(此結果在模擬器中運行)
從上面這些真實的數據來看,你就應該知道當你批量更新數據庫的時候應該利用事務處理!
總結:使用事務處理就是將所有任務執行完成以后將結果一次性提交到數據庫,如果此過程出現異常則會執行回滾操作,這樣節省了大量的重復提交環節所浪費的時間