【问题标题】:Lock oracle database before running the Delete/Load data scripts在运行删除/加载数据脚本之前锁定 oracle 数据库
【发布时间】:2012-06-03 09:11:10
【问题描述】:

我们每天午夜从 CI 运行 Junit 和 Selenium 测试用例。我们使用 Maven-SQL 插件预填充数据,如下所示。

          <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>sql-maven-plugin</artifactId>
                <version>1.3</version>
                <executions>
                    <execution>
                        <id>create-database-tables</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>execute</goal>
                        </goals>
                        <configuration>
                            <autocommit>false</autocommit>
                            <onError>continue</onError>
                            <srcFiles>
                                <srcFile>../sql/delete_data.sql</srcFile>
                                <srcFile>../sql/load_data.sql</srcFile>
                            </srcFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

由于不同用户同时构建,我们经常面临数据库死锁。我们认为的解决方案是在运行数据库脚本之前锁定数据库。

我们能否在运行脚本之前锁定数据库访问权限并在运行脚本后解锁它。

【问题讨论】:

  • 是不是因为多个用户同时运行以上代码导致死锁?
  • 4 个团队正在开发这个项目。由于通讯问题,它们同时运行。

标签: java oracle maven


【解决方案1】:

你可以做的是:

在脚本开始时尝试锁定一个表。

lock table <some_table> in exclusive mode nowait;

只有在没有其他进程锁定此表时才会成功。如果失败,另一个进程已经在运行。

如果您获得了锁,请运行脚本的其余部分。请注意,脚本中的任何提交或回滚都会结束锁定,因此请仅在脚本的最后提交或回滚。

还要确保锁定一个表,该表的唯一目的是为了以独占方式运行脚本。

【讨论】:

    【解决方案2】:

    用于测试的共享数据库从来都不是一个好主意,大概您知道这就是为什么您要询问如何一次限制对一个用户的访问。

    除了讲道.....我想提供liquibase 的左字段解决方案来管理数据库模式和数据填充。具有许多有用的功能,其中之一是它会自动锁定数据库并防止两个 liquibase 实例相互干扰。

    示例

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.myspotontheweb.db</groupId>
        <artifactId>liquibase-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <properties>
            <!-- Liquibase settings -->
            <liquibase.url>jdbc:h2:target/db1/liquibaseTest;AUTO_SERVER=TRUE</liquibase.url>
            <liquibase.driver>org.h2.Driver</liquibase.driver>
            <liquibase.username>user</liquibase.username>
            <liquibase.password>pass</liquibase.password>
            <liquibase.changeLogFile>com/myspotontheweb/db/changelog/db-changelog-master.xml</liquibase.changeLogFile>
            <liquibase.promptOnNonLocalDatabase>false</liquibase.promptOnNonLocalDatabase>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <version>1.3.162</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.liquibase</groupId>
                    <artifactId>liquibase-maven-plugin</artifactId>
                    <version>2.0.2</version>
                    <executions>
                        <execution>
                            <phase>process-resources</phase>
                            <goals>
                                <goal>update</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    

    【讨论】:

      【解决方案3】:

      这实际上取决于您如何使用数据库。如果不同的用户是不同的oracle用户,应该没有问题,因为每个用户都可以有自己的表,互不干扰。

      如果每个用户都连接到同一个 Oracle 用户,则可能存在冲突。如果每个测试都需要对所有资源的独占访问,您可以构建一个控制表来控制允许访问和不允许访问的人员。这应该在测试准备和测试结束步骤中进行编码才能有效。可以在表中进行简单的插入并检查“您的”插入是否是第一个。使用 dbms_lock 也是一个类似的选项。

      另一种方法是使用 Oracle 资源管理器,并将用于运行独占测试的 Oracle 数据库帐户的最大会话限制设置为 1。这样做,每次连接都会被拒绝,直到测试用户断开连接后连接槽再次可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-13
        • 2015-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-08
        • 2014-09-16
        • 1970-01-01
        相关资源
        最近更新 更多