1.什么叫数据库事务?
事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态.
一组逻辑操作单元:一个或多个DML操作.
2.事务处理的原则:保证所有事务都作为一个工作单元执行,即使出现了故障,都不能改变这种执行方式.当在一个事务中执行多个操作时,要么所有的操作都被提交(commit),那么这些修改就永久地保存下来,要么数据库管理系统将放弃所有的修改,整个事务回滚(rollback)到最初状态.
3.数据一旦提交,不可回滚
4.哪些操作会导致数据的自动提交?
1.DDL操作一旦执行,都会自动提交
在JDBC中即使SetAutoCommit(false)开启事务,对DDL操作是失效的
2.DML默认情况下,一旦执行,就会自动提交
我们可以通过SetAutoCommit(false)来开启事务,取消自动提交
事务的ACID特性
1.原子性(Atomicity):原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生.
2.一致性(Consistency):事务必须使数据库从一个一致性状态变换到另外一个一致性状态.
3.隔离性(Isolation):事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰.
4.持久性:(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响.
数据库并发存在的问题:
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题.
脏读:对于两个事务T1,T2. T1读取了已经被T2更新但没有提交的字段.之后若T2回滚,T1读取的内容就是临时无效的------------------------>出现在读为提交 1级事务隔离级别
不可重复读:对于两个事务T1,T2. T1读取了一个字段,然后T2更新了该字段.之后T1再次读该相同字段,值确不同了.--------------------------->第二级别,不可重复读,就是说别人改了,你这边再读就会读到不同数据
幻读:对于两个事务T1,T2. T1从一个表中读取了一个字段,然后T2在该表插入新数据了.之后T1在同一个事务中读到的是原先的数据-------------------->出现在第三个级别,可重复读
数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题.
一个事务与其他事务隔离的程度称为隔离级别.数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据库一致性就越好,但并发性能越弱
在 MySQL 的隔离级别为"读已提交"(Read Committed)时,当一个事务在对一条数据进行更新操作时,其他事务要等待这个数据更新操作的事务完成之后才能访问这条数据。这确保了并发事务之间的数据一致性,也意味着其他事务在第一个事务完成更新之前是无法读取到已更新的数据的。
在"读已提交"隔离级别下,每个事务都只能看到已提交的数据,并且其他未提交的事务对其是不可见的。这种行为是一种折中,既可以保障并发性能,又能维护数据的一致性。
因此,如果一个事务正在更新某一行数据,其他事务如果要对相同行进行更新,将会等待直到第一个事务的更新操作完成。这种等待是通过锁来实现的,以确保数据的一致性和完整性。
四种数据库隔离级别:
READ UNCOMMITTED(读未提交):允许事务读取未被其他事务提交的变更.会出现不可重复读和脏读现象
READ COMMITED(读以提交):只允许事务读取已经被其他事务提交的数据.避免脏读.但是出现不可重复读和幻读问题
REPEATABLE READ(可重复读):确保事务可以多次读到相同值.避免了脏读和不可重复度.但是幻读问题依旧存在
SERIALIZABLE(串行化.序列化读):确保事务可以从一个表中读取相同的行.禁止其他事务对该表执行增删改操作.所有并发问题都可以避免.但是性能就降低了.
Oracle支持的两种事务隔离级别:READ COMMITED和SERIALIZABLE.默认为READ COMMITED
Mysql数据库默认事务隔离级别是三级 Oracle默认事务隔离级别是二级 阿里云Mysql数据库默认是二级
即使你做了全局事务隔离级别,重启后默认恢复到初始级别:Mysql数据库默认事务隔离级别是三级 Oracle默认事务隔离级别是二级 阿里云Mysql数据库默认是二级
查看数据库事务隔离级别
select @@tx_isolation(老版本)
select @@global.tx_isolation(老版本)
select @@global.transaction_isolation(新版本)
设置全局事务隔离级别为读未提交:set global transaction isolation level read uncommitted;
设置全局事务隔离级别为读已提交:set global transaction isolation level read committed;
设置全局事务隔离级别为可重复读:set global transaction isolation level repeatable read;
设置全局事务隔离级别为序列化读:set global transaction isolation level serializable;
在数据库中,有两种设置事务隔离级别的方式:设置当前事务的隔离级别和设置全局事务隔离级别。
**设置当前事务的隔离级别:**这种设置方式只影响当前事务,不会对其他事务产生影响
例如:SET TRANSACTION ISOLATION LEVEL read committed;
在黑屏中开启事务命令:start transaction;或者SET autocommit = 0;或者SET autocommit = false;
提交事务命令:commit;
回滚事务:rollback;
conn.setTransactionIsolation(Connection.选择事务隔离级别);
上面代码可以控制当前事务的隔离级别,只限于当前事务.
当然你也可以通过
statement.execute( set global transaction isolation level read uncommitted )
executeupdate也行 这样就配置了全局事务隔离级别.在数据库服务器不重启的情况下一直有效
但是当数据库重启后又会恢复默认级别
所有事务隔离级别,当某个事务在update或者delete一条或多条数据时,其他事务不能同时update或delete该数据,需要等待事务结束.这一点是否违背事务隔离级别越高影响并发性能?????该排队还是需要排队