不支持 postgresql 事务隔离级别 4

Posted

技术标签:

【中文标题】不支持 postgresql 事务隔离级别 4【英文标题】:postgresql Transaction isolation level 4 not supported 【发布时间】:2018-10-23 16:19:00 【问题描述】:

我正在尝试创建表(postgres + 暴露 + ktor + JDBC),我得到了那个错误。

在下面找到我的配置:

build.gradle

compile group: 'postgresql', name: 'postgresql', version: '9.0-801.jdbc4'

Hello.kt

object Pays : Table() 
val id = integer("id").autoIncrement().primaryKey() // Column
val name = varchar("name", 50) // Column


fun main(args: Array) 
Database.connect("jdbc:postgresql://localhost/my_db", driver = "org.postgresql.Driver", user = "user", password = "password")

这是我遇到的错误

Caused by: org.postgresql.util.PSQLException: Transaction isolation level 4 not supported.
at org.postgresql.jdbc2.AbstractJdbc2Connection.setTransactionIsolation(AbstractJdbc2Connection.java:826)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:25)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:20)
at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction.getConnection(ThreadLocalTransactionManager.kt:29)
at org.jetbrains.exposed.sql.Transaction.getConnection(Transaction.kt)
at org.jetbrains.exposed.sql.Database.getMetadata$exposed(Database.kt:17)
at org.jetbrains.exposed.sql.Database$url$2.invoke(Database.kt:26)
at org.jetbrains.exposed.sql.Database$url$2.invoke(Database.kt:15)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at org.jetbrains.exposed.sql.Database.getUrl(Database.kt)
at org.jetbrains.exposed.sql.Database$dialect$2.invoke(Database.kt:29)
at org.jetbrains.exposed.sql.Database$dialect$2.invoke(Database.kt:15)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at org.jetbrains.exposed.sql.Database.getDialect$exposed(Database.kt)
at org.jetbrains.exposed.sql.vendors.DefaultKt.getCurrentDialect(Default.kt:319)
at org.jetbrains.exposed.sql.vendors.DefaultKt.getCurrentDialectIfAvailable(Default.kt:323)
at org.jetbrains.exposed.sql.Column.getOnDelete$exposed(Column.kt:14)

【问题讨论】:

尝试使用官方的 postgres 驱动程序mvnrepository.com/artifact/org.postgresql/postgresql 对我来说很好 最新版本是42.2.2,不是9.0-801 【参考方案1】:

阅读JDBC驱动9.0版本的源码,我明白了:

/*
 * You can call this method to try to change the transaction
 * isolation level using one of the TRANSACTION_* values.
 *
 * <B>Note:</B> setTransactionIsolation cannot be called while
 * in the middle of a transaction
 *
 * @param level one of the TRANSACTION_* isolation values with
 * the exception of TRANSACTION_NONE; some databases may
 * not support other values
 * @exception SQLException if a database access error occurs
 * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
 */
public void setTransactionIsolation(int level) throws SQLException

    checkClosed();

    if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
        throw new PSQLException(GT.tr("Cannot change transaction isolation level in the middle of a transaction."),
                                PSQLState.ACTIVE_SQL_TRANSACTION);

    String isolationLevelName = getIsolationLevelName(level);
    if (isolationLevelName == null)
        throw new PSQLException(GT.tr("Transaction isolation level 0 not supported.", new Integer(level)), PSQLState.NOT_IMPLEMENTED);

    String isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL " + isolationLevelName;
    execSQLUpdate(isolationLevelSQL); // nb: no BEGIN triggered

getIsolationLevelName 是这样定义的:

protected String getIsolationLevelName(int level)

    boolean pg80 = haveMinimumServerVersion("8.0");

    if (level == Connection.TRANSACTION_READ_COMMITTED)
    
        return "READ COMMITTED";
    
    else if (level == Connection.TRANSACTION_SERIALIZABLE)
    
        return "SERIALIZABLE";
    
    else if (pg80 && level == Connection.TRANSACTION_READ_UNCOMMITTED)
    
        return "READ UNCOMMITTED";
    
    else if (pg80 && level == Connection.TRANSACTION_REPEATABLE_READ)
    
        return "REPEATABLE READ";
    

    return null;

由于java.sql.Connection.TRANSACTION_REPEATABLE_READ is 4,你的错误信息只能说明pg80就是false

因此,唯一的解释是您实际上使用的 PostgreSQL 服务器版本早于 8.0,或者更有可能是您使用的是 PostgreSQL v10 并且 JDBC 驱动程序太旧而无法理解新的两位数版本编号系统。

在第一种情况下,您应该升级 PostgreSQL,但无论如何,您应该使用当前版本的 JDBC 驱动程序。那应该可以解决您的问题。

【讨论】:

谢谢,更新到 org.postgresql:postgresql:42.2.2 后解决了我的问题【参考方案2】:

请尝试更新 build.gradle

compile group: 'org.postgresql', name: 'postgresql', version: '9.4-1200-jdbc41'

【讨论】:

9.4-1200-jdbc41 也已经过时了,你不应该使用它

以上是关于不支持 postgresql 事务隔离级别 4的主要内容,如果未能解决你的问题,请参考以下文章

Odoo 后端数据库postgreSQL事务级别

PostgreSQL事务隔离级别

使用Django和PostgreSQL进行事务(@atomic)的默认隔离级别

MySQL事务隔离级别详解

MySQL事务隔离级别详解

MySQL事务隔离级别详解