撰写时间:2019年06月04日
Mysql的引擎
mysql-5.5.5开始,InnoDB 作为默认存储引擎,以前是MyISAM引擎
MyISAM引擎和InnoDB引擎的比较:
MyISAM 是非事务安全型的,而 InnoDB 是事务安全型的。
MyISAM 锁的粒度是表级,而 InnoDB 支持行级锁定。
MyISAM 支持全文类型索引,而 InnoDB 不支持全文索引。
MyISAM 相对简单,所以在效率上要优于 InnoDB,小型应用可以考虑使用 MyISAM。
MyISAM 表是保存成文件的形式,在跨平台的数据转移中使用 MyISAM 存储会省去 不少的麻烦。
InnoDB 表比 MyISAM 表更安全,可以在保证数据不会丢失的情况下,切换非事务 表到事务表(alter table tablename type=innodb)。
default-storage-engine=InnoDB
default-storage-engine=MYISAM
事务(回滚):当事务正常提交上去的时候,下一个事务失败的时候
事务要回滚到上一条数据。旧引擎MyISAM 就是不支持回滚,所以不支持事务
悲观锁:即很悲观 ,每次拿数据的时候都觉得数据会被人更改,所以拿数据的时
候就把这条记录锁掉,这样别人就没办法改这条数据了,一直到你的锁释放。
* 悲观锁的实现采用的是数据库内部的锁机制 for update
* 在查询数据的时候先用for update把这条数据锁住,然后更改完这条数据再
提交。这样别的线程没法更新这条数据,也就保证了不会丢失更新
行级锁
锁一条数据 改其他数据没影响的
需要数据库支持
旧的那个引擎是不支持行级锁的
public class DemoLock1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
String sql = "Select * From user where id=5 for update";
ps = conn.prepareStatement(sql);
// 执行返回结果
rs = ps.executeQuery();
while (rs.next()) {
System.out.println("id:" + rs.getInt(1)
+ " name:"+ rs.getString(2)
+ " passwpord:" + rs.getString(3));
sql = "UPDATE USER SET NAME ='cbd' WHERE id =5";
ps = conn.prepareStatement(sql);
ps.executeUpdate();
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}
}
}
悲观锁在 高并发的时候会出现严重问题
悲观锁给人的感觉就是 一直在等待 然后给人返回一个超时
不如直接给出一个操作不成功
这就是出现了乐观锁
*查询数据的时候总觉得不会有人更改数据,等到更新的时候在判断这个数据有没
有被人更改,有人更改了则本次更新失败
*通过在表里面加一个版本号的形式
乐观锁是通过代码逻辑来实现的 而不是通过数据库内部的锁机制
当操作某条数据的时候 先查询出来获取某个值,然后已该值为修改的where 条件,
当这条数据先被修改过,那么那个值就发生改变,然后修改的where条件获取的是
进来时查询到的值,是修改前的,然后跟当前最新值不对应,然后就返回一个修改
不成功。
public class DemoLock2 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
int r=0;
try {
conn=DBUtil.getConnection();
conn.setAutoCommit(false);
String sql="Select * From user where id=5";
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
while (rs.next()) {
int version=rs.getInt("version");
sql="update user set name='蔡一0',version=version+1
where id=5 and version=?";
ps=conn.prepareStatement(sql);
ps.setInt(1, version);
r=ps.executeUpdate();
}
conn.commit();
if (r>0) {
System.out.println("修改成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
finally{
DBUtil.close(conn, ps, rs);
}
}
}
测试看效果:断点执行,在提交之前一定要断点,在断点那停的时候去数据库手动修改
加锁的那条数据,看看实际效果是不是跟说的一样。