事务
1.JDBC事务
1.1事务
事务:是一个非常重要的东西,一定要认真对待。一件事儿要么同时成,要么同时不成,不能出现事成一半的问题。
如果半道出现问题,请回滚到起初的样子,rollback.
1.2演示
问题: 演示的代码显示:Rose 扣款10元成功,但是因为中间出现异常,导致Jack账户上并没有增加10元。
原因是:jdbc的事务是自动提交的,每执行一次SQL就提交一次事务。
改:
1) 将自动提交事务,改为手动提交 connection.setAutoCommit(false);
2) 如果中间没有出现异常,再提交事务。connection.commit();
3) 如果中间有异常,就回滚事务 connection.rollback();
2MySQL事务
2.1默认事务
默认情况下,我们的每一条SQL语句都是默认提交的。
update account set money=money-10 where name='Rose';
update account set money=money+10 where name='Jack';
2.2手动事务
如果遇到类似于转账的操作,几条SQL要么同时成功,要么回滚
1、手动开启事务:start transaction;
2、执行需要执行的SQL:
update account set money=money-10 where name='Rose';
update account set money=money+10 where name='Jack';
我们发现,手动开启事务后,如果事务不提交,update语句更新的数据不显示。
3、手动开启事务后,必须手动提交 commit ,数据才算更新或保存。
4、如果中间有问题,可以选择不提交,使用回滚rollback操作,这个时候可以提交,但是数据已经变成原来的数据了。
2.3事务设置
自动提交和手动提交的开关【了解即可,不要改】
select @@autocommit; // 1代表SQL自动提交,0代表手动提交
set @@autocommit=0;
可以修改,但是最好不要改,因为我们的代码大部分都是依赖自动提交的。
2.4提交和回滚
一旦我们的客户端发送给服务器指令: start transaction;
后面执行的所有SQL,都会存入到临时文件中,临时文件里面的数据只有等到commit,或者rollback 才会清空临时文件。
commit 清空临时文件,将正确数据存入到真正的数据库中,rollback 只是清空记录,不做任何操作。
2.5回滚点
savapoint
start transaction;
update account set money=money-1 where name='Jack';
update account set money=money-1 where name='Jack';
update account set money=money-1 where name='Jack';
savepoint three_point;
update account set money=money-1 where name='Jack';
update account set money=money-1 where name='Jack';
rollback to three_point;
commit;// 发现真正的数据,只减了三次钱
3.事务的隔离级别
3.1事务的四大特征 ACID
原子性(Atomicity):每个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功
要么都失败。
一致性(Consistency): 事务在执行前数据库的状态与执行后数据库的状态保持一致。如:转账前2 个人的
总金额是 2000,转账后 2 个人总金额也是 2000
隔离性(Isolation):事务与事务之间不应该相互影响,执行时保持隔离的状态。
持久性(Durability): 一旦事务执行成功,对数据库的修改是持久的。就算关机,也是保存下来的。
3.2事务的隔离级别
事务的隔离级别
同一时间: 张三转账,李四转账,王五存钱,赵六取钱.....
多个人同时操作同一个数据库,虽然理想情况下我们不想让他们之前有任何 的联系,
但是事与愿违,因为数据库无法办到,所以我们只能取舍!!!
引发:脏读,幻读,不可重复读三大问题。
为了解决这些问题,各大数据库厂商推出了数据库的四个隔离级别来应对这些问题
3.3四大隔离级别的特点
四大隔离级别 安全性和执行效率永远是对立的
mySQL 默认的给力级别是:REPEATABLE-READ select @@tx_isolation;
1) 读未提交 read uncommitted 虽然引发的问题很多,但是运行效率极高
修改数据库隔离级别:
set global transaction isolation level read uncommitted;
会出现脏读、幻读、不可重复读的问题。
脏读:一个事务读取到了另一个事务的尚未提交的数据。
一个问题:Rose 给Jack转钱,Rose没有提交的情况下,Jack能把钱取走吗?
mysql 默认存储引擎是InnoDB, InnoDB数据库的锁是行级锁。
如果一个事务操作某一行数据,没有操作完的情况下,另一个事务是无法操作的。
结论:取不走。
2) 读已提交 read committed
set global transaction isolation level read committed;
这个隔离级别可以解决脏读的问题,但是无法解决不可重复读的问题。
不可重复读的问题:在我们的一个事务中,读取到的数据必须是一样的,不能变化。如果变化,说明出现了不可重复读的问题。
在同一个事务中,我们第一次读取Jack数据,和后面读取到的杰克的数据,不一样。
3)repeatable read 可重复度级别 --能够解决不可重复度的问题
set global transaction isolation level repeatable read;
我们看到,隔离级别一提升,在同一个事务中多次读取到的数据,一直没有发生变化,问题解决
4)幻读的问题,mysql无法演示。
5) serializable 串行化 可以解决所有安全问题,但是效果类似于锁表
每次只能有一个人操作你的数据库。
4.数据库管理 DCL
4.1关于用户的操作
// 创建用户
create user 'laoyan'@'localhost' identified by 'laoyan';
// 给用户赋权限
grant all on . to 'laoyan'@'localhost';
// 收回用户的权限
revoke all on . from 'laoyan'@'localhost';
// 查看某个用户的权限:
show grants for 'root'@'localhost';
// 删除权限
drop user 'laoyan'@'localhost';
4.2关于默认四张表
安装完数据库之后,默认会有四张表:mysql,test, information_xxx,performance_xxx
这四个表除了test,其余不要乱动,否则数据库崩溃。
4.3如何修改数据库密码(了解)
4.3.1第一种
// 修改用户的密码
第一种是可以登录进去,之前的密码还记得:
5.5 版本:
use mysql;
update user set password=password('123456');
5.7 版本:
没有password字段了,修改authentication_string
update user set authentication_string=password('123456');
重启服务才能生效。
4.3.2第二种
第二种是把账号密码忘记了
- cmd -- > net stop mysql 停止mysql服务
- 需要管理员运行该cmd
- 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
- 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
- use mysql;
- update user set password = password('你的新密码') where user = 'root';
- 关闭两个窗口
- 打开任务管理器,手动结束mysqld.exe 的进程
- 启动mysql服务
- 使用新密码登录。
4.4如何配置mysql服务器的远程连接
如果远程连接没有开,如何开启?
第一种(改表法): % 找到mysql数据库中的user表,找到root用户,将Host中的localhost修改为%,重启服务。
第二种(授权法):
GRANT ALL PRIVILEGES ON . TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;