示例:

char insert_sql[128] = {0};for (int i=0; i<10000; ++i){    sprintf(insert_sql, "insert into bindtest values(%d, %d)", i, i*100);    ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);    if (ret != SQLITE_OK)    {        printf("insert fail\n");        break;    }    sqlite3_free(errmsg);}
SQLite执行在一个事务中的每条语句,反对读事务和写事务。应用程序只能是在读或写事务中能力从数据库中读数据。应用程序只能在写事务中能力向数据库中写数据。应用程序不须要明确通知SQLite去执行事务中的单个SQL语句,SQLite时主动这样做的,这是默认行为,这样的零碎叫做主动提交模式。这些事务被叫做主动事务,或零碎级事务。对于一个select语句,SQLite建设一个读事务,对于一个非select语句,SQLite先建设一个读事务,再把它转换成写事务。每个事务都在语句执行完结时被提交或被终止。应用程序不晓得有零碎事务,应用程序只是把SQL语句提交给SQLite,由SQLite再去解决对于ACID的属性,应用程序接管从SQLite执行SQL返回的后果。一个应用程序能够在雷同的数据库连贯上引发执行select语句(读事务)的并行执行,然而只能在一个闲暇连贯上引起一个非select语句(写事务)的执行。主动提交模式可能对某些应用程序来讲代价过高,尤其是那些写密集的应用程序,因为对于每一个非select语句,SQLite须要反复关上,写入,敞开日志文件。在主动提交模式中,在每条语句执行的最初,SQLite抛弃页缓冲。每条语句执行都会从新结构缓冲区,从新结构缓冲区是破费大,低效的口头,因为会调用磁盘I/O。并且,存在并发管制的开销,因为对每一句SQL语句的执行,应用程序须要从新获取和开释对数据库文件的锁。这种开销会使性能显著降落(尤其是大型应用程序),并只能以关上一个包含了很多SQL语句的用户级别的事务来加重这种状况(如:关上多个数据库)。应用程序能够用begin命令手动的开始一个新的事务,这种事务被称为用户级事务(或用户事务)。当begin执行后,SQLite来到默认的主动提交模式,在语句完结时不会调用commit或abort。也不会抛弃该页的缓冲。间断的SQL语句是整个事物的一部分,当应用程序执行commit/respectively/rollback指令时,SQLite提交或别离或停止事务。如果当事务停止或失败,或应用程序敞开连贯,则整个事务回滚。SQLite在事务实现时复原到主动提交模式上来。
begin开始事务
commit保留更改
rollback回滚所作的更改
事务回滚
sqlite> select * from stu;0|小黑1|小白sqlite> update stu set name='人类';sqlite> select * from stu;0|人类1|人类sqlite> rollback;sqlite> select * from stu;0|小黑1|小白
事务提交
sqlite> select * from stu;0|小黑1|小白sqlite> begin;sqlite> select * from stu;0|小黑1|小白sqlite> update stu set name='人类';sqlite> select * from stu;0|人类1|人类sqlite> commit;sqlite> select * from stu;0|人类1|人类sqlite> rollback;Error: cannot rollback - no transaction is active
编程试验:事务对插入效率的影响
#include <stdio.h>#include <sqlite3.h>#include <time.h>int main(){    // 1. 关上数据库    sqlite3 *ppdb = NULL;    int ret = sqlite3_open("test.db", &ppdb);    if (ret != SQLITE_OK)    {        printf("open fail\n");        return -1;    }    // 2. 执行 sql 语句    // 2.1 创建表格 create table apitest(id int, number int);    const char *create_sql = "create table if not exists testTransaction(id int, number int)";    char *errmsg = NULL;    ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);    if (ret != SQLITE_OK)    {        printf("%s\n", errmsg);    }    sqlite3_free(errmsg);    // 2.2 数据直接插入 ==============================    struct timeval start;    struct timeval end;    char insert_sql[128] = {0};    mingw_gettimeofday(&start, NULL);    for (int i=0; i<1000; ++i)    {        sprintf(insert_sql, "insert into testTransaction values(%d, %d)", i, i*100);        ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);        if (ret != SQLITE_OK)        {            printf("insert fail\n");            break;        }        sqlite3_free(errmsg);    }    mingw_gettimeofday(&end, NULL);    printf("insert directly: %ld s\n", end.tv_sec - start.tv_sec);    // 2.3 数据直接插入-事务 ==============================    mingw_gettimeofday(&start, NULL);    sqlite3_exec(ppdb, "begin", NULL, NULL, NULL);    for (int i=0; i<1000; ++i)    {        sprintf(insert_sql, "insert into testTransaction values(%d, %d)", i, i*100);        ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);        if (ret != SQLITE_OK)        {            printf("insert fail\n");            break;        }        sqlite3_free(errmsg);    }    sqlite3_exec(ppdb, "commit", NULL, NULL, NULL);    mingw_gettimeofday(&end, NULL);    printf("insert directly(transaction): %ld us\n", end.tv_usec - start.tv_usec);    // 3. 敞开数据库    ret = sqlite3_close(ppdb);    if (ret != SQLITE_OK)    {        printf("close fail\n");        return -1;    }    return 0;}

输入:

insert directly: 7 sinsert directly(transaction): 10996 us