初始化连接
MYSQL *mysql = mysql_init(NULL);
处理结果
MYSQL_RES mysql_store_result(MYSQL *mysql); //获取由mysql_query()函数返回的结果,注意查询成功是0,失败为非0.所以使用时一般if(。。。){} void mysql_free_result(MYSQL_RES *result); //释放数据结构MYSQL_RES占据的内存空间 my_ulonglong mysql_num_rows(MYSQL_RES *result); //SQL语句结果的行数 unsigned int mysql_num_fields(MYSQL_RES *result); ///SQL语句结果的列数 MYSQL_ROW mysql_fetch_row(MYSQL_RES *result); //从结果当中取出一行
事务特性ACID
原子性atomicity
- 整个事务的操作要嘛全部commit,要嘛全部rollback,不可分割
一致性consistency
- 狭义类似于物质守恒,数据从一个状态,通过事务要嘛不变,要嘛一致性地演变为另一种状态
隔离性isolation
- 事务之间的关联性
- 关联性可强可弱
持久性durability
一旦事务commit或rollback,事务对数据库的改变应当是永久的
数据操作可能遇到的问题
脏读(Dirty read)
一个事务读取到了另一个事务还未提交的数据
- a给b转账,a扣款是个过程。当下时刻本该是扣了款的状态,在此过程却有人去读它的余额,因为该过程未完成(还没commit),读到的是没扣款的状态。
不可重复读(Nonrepeatable read)
同一事务,针对同一数据,前后读取数据却不同
- a事务前后读了两次余额,但在两次读的中间,b事务对余额做了修改,便导致读到的余额不同了
幻读(Phantom read)
一个事务内读到的条目数变了
- 其实就跟不可重复读原理类似,都是在两次读的中间,数据被
修改
了。只是不可重复读是读到了数据内容变化(如update set),而幻读读到了数据条目数的变化(如 insert into)
隔离级别
适用情况:俩数据库连接,一个在增删改,另一个在查
查看和修改隔离级别
SELECT @@GLOBAL.TRANSACTION_ISOLATION; -- 查看整个数据的设置 SELECT @@SESSION.TRANSACTION_ISOLATION; -- 查看一个连接的隔离级别 SET GLOBAL TRANSACTION ISOLATION LEVEL [SERIALIZABLE | REPEATABLE READ| ...]; SET SESSION TRANSACTION ISOLATION LEVEL [SERIALIZABLE | REPEATABLE READ| ...];
如:
set global transaction isolation level read uncommitted; set global transaction isolation level repeatable read;
提前说明,实际上这些隔离级别都是针对读端的,只是在读端事务中,查询的结果会因为隔离级别的不同而不同。
不过navicat图形化进行查询,似乎情况有所不同,比如即使已全局设置了隔离级别为读已提交,事务进行数据修改后未提交,navicat图形化查询也是修改后的数据。rollback之后数据又回来了。似乎级别默认是读未提交且不会被直接更改。
读未提交(READ UNCOMMITE)
READ UNCOMMITED
级事务的修改,即使没有提交,对其他事务也可见
会产生问题:脏读,不可重复读,幻读
读已提交(READ COMMITED)
READ COMMITED
级事物的修改在提交前,其他事务不可见
会产生问题:不可重复读,幻读。
但不会产生脏读了
可重复读(REPEATABLE READ)
REPEATABLE READ
级MySQL的默认隔离级别
一个事务开始后,保证多次读取的结果一致
- 在REPEATABLE READ隔离级别下,MySQL会创建一个一致性视图,即事务开始时的视图。所有的
SELECT
语句将基于这个视图返回结果,即使其他事务进行了更新,也不会影响当前事务的视图。- 所以一般情况下直观来说,读端事务在事务开始时创建一个快照表,之后就对着这个快照表查数据了,不会因为其他事务对数据的修改而改变查询的结果
仍会存在一部分幻读问题,解决了脏读与不可重复读
- 关于幻读,该隔离级别演示结果上看起来没有幻读问题,实际上在MySQl的可重复读隔离级别上,仍是存在幻读的问题
序列化(SERIALIZABLE)
SERIALIZABLE
级强制事务串行执行,在事务读取每一行数据时都上锁,以保证事务的先后顺序。也就因此不存在多个事务同时执行的情况了(无上述问题)。
例如一个事务,仅一句select * from table 就会锁住table中数据。在该事务commit前其他事务都不可增删改
各隔离级别的对比
隔离级别 | 脏读 | 不可重复读 | 虚幻读 |
---|---|---|---|
读未提交(read uncommitted) | √ | √ | √ |
读已提交(read committed) | X | √ | √ |
可重复读(repeatable read) | X | X | √-× |
串行化(serializable) | X | X | X |