1-什么是事务:
事务就是一种机制,一个操作序列,包含了一株数据操作的命令,事务将这个命令一起提交,这个命令要么一起成功要么一起失败
比如:淘宝买东西我支付宝总钱100元,商家总余额200元,然我50买他的东西,所以我的支付宝应该减50,商家加50,写代码时候如果我的支付宝减过了50那么商家的再加50是没错的,但是如果我减了然后出现异常了商家还没有加50,那么就会出现我钱减少了商家钱不变的情况。
Mysql默认就自带事务,流程就是:开启事务----(出现异常就是回滚一起失败)没有异常-----提交事务。 代码:开启事务-start transaction 提交事务(如果一切正常)-commit 回滚事务(如果异常)-rollback
MySQL的手动提交事务 set autocommit = 0; -- 0:OFF 1:ON 这个可以修改是否更改自动提交事务为自动的还是手动的,这个修改只是一次性的,就是只是针对这次链接有用,如果关闭连接再次打开链接则就又变成自动的了。 show variable like '%commit%'是显示当前事务为自动还是手动
start transaction; -- 手动开启事务
update account set money = money-100 where name='a'; -- 执行减100命令
update account set money = money+100 where name='b'; -- 执行加100命令
commit; --提交事务,如果出现异常就两条一起回滚
如果commit了以后那么就是永久性的改变不可回滚了。事务只是针对DML的也就是增删改
事务的四大特性ACID(面试高频): A(Atomicity 原子性)C(Consistensy 一致性)I(Isolation 隔离性)D(Durability 持久性)
A-原子性:事务包装的一组sql数据,要么都成功要么都失败
C-一致性:是事务从一个一致性的状态变为另外一个一致性的状态, 比如张三有500,李四有500,合是1000,张三给李四一百,那么张三400,李四600,他们的合还是1000.这就是一个一致性状态变为另外一个执行状态,一致性大多数依赖于原子性合逻辑
I-隔离性: 彼此隔离不受影响,例子:张三,李四,马六都给王五转账,张三转账失败了,他不影响两外两个人的转账,他们彼此是独立的。
D-持久性:是一个事务如果提交了,那么他就是永久性改变的,就是数据库异常从新启动他依旧是被改变过了
事务的并发访问引发的三个问题(面试):多个事物之间是相互隔离不受影响的,但是如果隔离级别设置不够就会引发并发问题 1-脏读 2-不可重复读 3-幻读
1-脏读(开发中一定避免):一个事务读取了另外一个还未提交的数据,如下图:事务A去读id为1的数据,还没开始读事务B就把id为1的age改为18,这时候事务A查到的age=16,但是事务B又Rollback了,导致事务A读到的数据就是错误的
2-不可重复读(开发中允许的):一个事务多次读取数据内容不一致,一个事务不同时间段多次读取数据结果不同
3-幻读(开发中允许的):一个事务内读到了别的事务插入或者删除的数据,强调的是行记录数,当第一次读取是一行,再来读就是两行
事务的隔离级别:
1-读未提交:最不安全的,有脏读
2-读已提交:这个是最好的Oracle和SQL Server默认的级别
3-可重复读:MYSQL默认隔离级别
4-串行化: 避免了脏读,可重复读,幻读全避免了但是性能是最低的
MySQL性能:
性能分了两种:1-硬件优化 2-软件优化 我们程序员主要是负责软优化
软优化:在操作和设计数据库方面上进行的优化,表结构和sql语句(重点)
分析执行次数较多的语句
查看当前数据库是查询密集型还是修改密集型 show global status ike 'Innode_rows%'; 查看这个表增删改查的次数
1:查询密集型:查询用的比较多
1-1:索引优化:如果没有索引的情况下从一千万条数据下查询一条数据需要大概6s,这是什么都没有的情况下,这时候可以用索引优化,索引优化是MySQL高效获取数据的数据结构,索引都有主键索引(主键约束=非空+唯一)+提高效率查询,唯一索引:唯一约束+提高查询效率 普通索引:提高查询效率 组合联合索引:(多个字段组成索引) hash索引:他是效率最高的使用key-value,但是不适用全局查找
1-2:索引优化后占用内存更大,他只是优化查询,如果是增删改不推荐效率反而低了
1-3:索引底层是B+Tree数据结构,一个大的节点是16kb储存,只存储索引和指针
B+Tree一层表示我们查询数据经历一次磁盘IO,也就是说2000万挑数据中查找某个数据只需要三次磁盘IO就可以了所以相对来说还是比较快的,磁盘IO越小越好,其实他访问了两次,因为在启动MySQL的时候就已经自动把第一层给弄好了,再查询的时候就不会经历第一次的磁盘IO了
2:修改密集型:修改会有elasticsearch等等相对应的技术,比如购物车就是经常需要修改的
JDBC:其实实际开发中用不到但是spring框架和mybaties其实都是将JDBC封装到底层了,这是原理
JDBC链接数据库的步骤:
//1注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2获取链接
Connection con = DriverManager.getConnection(url,username,pwd);
//3定义SQL语句
String sql = "select * from....";
//4获取执行Sql语句的对象
Statement stmt = con.createStatement();
//5执行sql
stml.executQuery(sql); //这是查询如果是修改就是stml.executUpdate(sql);
第一步的祖册驱动:用到了DriverManager类
DriverManager类:作用 1:注册驱动 2:获取数据库链接
1:DriverManager有一个registerDriver它是不管是那个数据库厂商都要实现这个接口中的,而上边代码是在Class.forName("com.mysql.jdbc.Driver");实现的,因为com.mysql.jdbc.Driver的Driver就是实现了java的Driver,源码中就是有一个静态代码块来DriverManager.registerDriver调用这个registerDriver静态方法注册驱动的,其实在4版本以后就不用Class.forName("com.mysql.jdbc.Driver");了,因为第二步Connection con = DriverManager.getConnection中会调用Driver,只要调用因为registerDriver是静态的所以就注册了。
第二部链接数据库:Connection con = DriverManager.getConnection(url,,username,pwd);
其中url的地址是 jdbc:mysql://127.0.0.1:3306/数据库
但是如果是本地连接可以直接jdbc:mysql://localhost:3306/数据库