Я пытаюсь заблокировать одновременную модификацию во время миграции базы данных, мой подход заключается в блокировке существующей таблицы t
(prereq) с использованием SELECT ... FOR UPDATE
и достижения миграции во время блокировки.SELECT FOR UPDATE для блокировки базы данных во время миграции
Таким образом, я создал простой образец, как следующее:
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/testdb", "root", "");
conn.setAutoCommit(false);
statement = conn.createStatement();
ResultSet rs = statement.executeQuery("SELECT id FROM t FOR UPDATE");
rs.next();
System.out.println(rs.getInt(1));
System.out.println("Sleeping...");
Thread.sleep(10000);
statement.executeUpdate("CREATE TABLE t2 (id int PRIMARY KEY)");
// Release lock
statement.executeUpdate("UPDATE t SET id = 2 WHERE id = 1");
conn.commit();
statement.close();
conn.close();
t
, где находится фиктивный таблица с только id int PRIMARY KEY
.
Я установил Thread.sleep(10000);
, чтобы имитировать длительный процесс. Во время Thread.sleep(10000);
я бегу второй (аналогичный кусок кода) для имитации параллелизм
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/testdb", "root", "");
Statement statement = conn.createStatement();
conn.setAutoCommit(false);
statement = conn.createStatement();
ResultSet rs = statement.executeQuery("SELECT id FROM t FOR UPDATE");
rs.next();
System.out.println(rs.getInt(1));
conn.commit();
statement.close();
conn.close();
Но я ожидал, что код печати 2
.. напечатанное 1
.
Когда я проверять MySQL общего журнал я вижу, что вещь
438 Query SET autocommit=0
438 Query SELECT id FROM t FOR UPDATE
439 Query /* mysql-connector-java-5.1.35 (Revision: 5fb9c5849535c13917c2cf9baaece6ef9693ef27) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'license' OR Variable_name = 'init_connect'
439 Query /* mysql-connector-java-5.1.35 (Revision: 5fb9c5849535c13917c2cf9baaece6ef9693ef27) */SELECT @@session.auto_increment_increment
439 Query SET character_set_results = NULL
439 Query SET autocommit=1
439 Query SET sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'
439 Query SET autocommit=0
439 Query SELECT id FROM t FOR UPDATE
438 Query CREATE TABLE t2 (id int PRIMARY KEY)
439 Query commit
439 Query rollback
439 Quit
438 Query UPDATE t SET id = 2 WHERE id = 1
438 Query commit
438 Query rollback
После CREATE TABLE t2...
сделки (сессия 2) поручена эта блокировка выпуска, но я в autoCommit(false)
почему MySQL сила commit
на этом.
я могу также missunderstand как SELECT ... FOR UPDATE
работы ...
UPDATE: испытываться без Java и JDBC с использованием MySQL клиенту
SESSION1> CREATE TABLE t (id int PRIMARY KEY) ENGINE=INNODB;
SESSION1> INSERT INTO t VALUES (1);
SESSION1> BEGIN;
SESSION1> SELECT id FROM t FOR UPDATE;
SESSION2> BEGIN;
SESSION2> SELECT id FROM t FOR UPDATE;
--> HERE SESSION2 is stuck (expected behavior)
SESSION1> CREATE TABLE t2 (id int PRIMARY KEY) ENGINE=INNODB;
--> HERE SESSION2 is unlock returning
+----+
| id |
+----+
| 1 |
+----+
1 row in set (4.15 sec)
кажется, SELECT ... FOR UPDATE
с DLL заявление не работает как я ожидал
Да, но обе таблицы используют innodb. И второй 'SELECT FOR UPDATE' действительно застревает во время' Thread.sleep' до первого сеанса create table – Kakawait
Я только что редактировал мой вопрос, чтобы добавить дополнительную информацию. И я использую innodb (принудительный пример mysql cli), это по умолчанию для моего MySQL 5.6 – Kakawait