JAVA程序对MYSQL数据库加锁实验

ⅰ亾dé卋堺 提交于 2019-11-27 15:22:31

以下实验仅在MySQL 5.0.45做的实验.

方法1:用mysql命令锁住表.

	  public void test() {

		String sql = "lock tables aa1 write";
		// 或String sql = "lock tables aa1 read";
		// 如果想锁多个表 lock tables aa1 read ,aa2 write , .....
		String sql1 = "select * from aa1 ";

		String sql2 = "unlock tables";
		try {
			this.pstmt = conn.prepareStatement(sql);
			this.pstmt1 = conn.prepareStatement(sql1);
			this.pstmt2 = conn.prepareStatement(sql2);
			pstmt.executeQuery();
			pstmt1.executeQuery();
			pstmt2.executeQuery();

		} catch (Exception e) {
			System.out.println("异常" + e.getMessage());
		}

	}

一、对于read lock 和 write lock官方说明:
   1.如果一个线程获得一个表的READ锁定,该线程(和所有其它线程)只能从该表中读取。
      如果一个线程获得一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。
      其它的线程被阻止,直到锁定被释放时为止。

   2.当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。
      虽然使用LOCKTABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。
      同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,
      在此情况下,您必须分别获得对每个别名的锁定。

二、对与read lock 和 write lock个人说明:
    1.read lock 和 write lock 是线程级(表级别).
    2.在同一个会话中加了read lock锁. 只能对这个表进行读操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
       但是在不同会话中,只能对加了read lock的表进行读操作.但可以对read lock以外的表进行增、删、改、查的操作.
    3.在同一个会话中加了write lock锁.只能对这个表进行读、写操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
      但是在不同会话中,无法对加了write lock的表进行读、写操作.但可以对write lock以外的表进行增、删、改、查的操作.
   4.如果表中使用了别名.(SELECT * FROM aa1 AS byname_table) 
      在对aa1加锁时,必须把别名加上去(lock tables aa1 as byname_table read)
      在同一个会话中.必须使用别名进行查询.
      在不同的会话中.可以不需要使用别名进行查询.
   5.在多个会话中可以对同一个表进行lock read操作.但不能在多个会话中对同一个表进行lock write操作(这些锁将等待已锁的表释放自身的线程锁)
     如果多个会话对同一个表进行lock read操作.那么在这些会话中,也只能对以锁的表进行读操作.
   6.如果要你锁住了一个表,需要嵌套查询.你必须使用别名,并且,要锁定别名.
     例如.lock table aa1 read ,aa1 as byname_table read;
     select * from aa1 where id in (select * from aa1 as xx  where id=2);   
   7.解锁必须用unlock tables;

   另:
      在Java程序中,要想解锁,需要调用 unlock tables来解锁.
      如果没有调用unlock tables. 
      关闭connection 、程序结束 、调用GC 都能解锁.      

方法2:用记录锁锁表. 

	  public void test() {

		String sql = "select * from aa1 for update"; 
                // select * from aa1 lock in share mode;

		try {
			conn.setAutoCommit(false);
			this.pstmt = conn.prepareStatement(sql);
			pstmt.executeQuery();

		} catch (Exception e) {
			System.out.println("异常" + e.getMessage());
		}

	}

1.for update 与 lock in share mode 属于行级锁和页级锁

2.for update 排它锁,lock in share mode 共享锁

3.对于记录锁.必须开启事务.

4.行级锁定事实上是索引记录的锁定.只要是用索引扫描的行(或没索引全表扫描的行),都将被锁住.

5.在不同的隔离级别下还会使用next-key locking算法.即所扫描的行之间的“间隙”也会也锁住(在Repeatable read和Serializable隔离级别下有间隙锁).

6.在mysql中共享锁的含义是:在被共享锁锁住的行,即使内容被修改且并没有提交.在另一个会话中依然看到最新修改的信息.

   在同一会话中加上了共享锁.可以对这个表以及这个表以外的所有表进行增、删、改、查的操作.

   在不同的会话中.可以查到共享锁锁住行的最新消息.但是在Read Uncommitted隔离级别下不能对锁住的表进行删,

    改操作.(需要等待锁释放才能操作...)
                     在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
                     在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
                     在Serializable隔离级别下不能对锁住行进行增、删、改操作.  (需要等待锁释放才能操作...)

7.在mysql中排他锁的含义是:在被排它锁锁住的行,内容修改并没提交,在另一个会话中不会看到最新修改的信息。

   在不同的会话中.可以查到共享锁锁住行的最新消息.但是Read Uncommitted隔离级别下不能对锁住的表进行删,

    改操作.(需要等待锁释放才能操作...)
                     在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
                     在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
                     在Serializable隔离级别下不能对锁住行进行增、删、改操作. (需要等待锁释放才能操作...)   

8.在同一个会话中的可以叠加多个共享锁和排他锁.在多个会话中,需要等待锁的释放.

9.SQL中的update 与 for update是一样的原理.

10.等待超时的参数设置:innodb_lock_wait_timeout=50 (单位秒).

11.任何可以触发事务提交的命令,都可以关闭共享锁和排它锁.

                       

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!