【问题标题】:Get UnCommitted Data in MySQL在 MySQL 中获取未提交的数据
【发布时间】:2015-11-25 21:15:21
【问题描述】:

SQL Server 中,我们可以在SQL Queries 下方写入以获取数据库中未提交的数据。这意味着数据仍在交易中,交易未完成。

SQL Server 查询

Select * from TableName With(NoLock);

即使表被锁定,MySQL 数据库中是否有任何等价物来获取数据?我正在 PHP CodeIgnitor 中尝试这个

【问题讨论】:

标签: php mysql codeigniter sql-server-2012 codeigniter-3


【解决方案1】:

找到一篇标题为“MySQL NOLOCK 语法”的文章

http://itecsoftware.com/with-nolock-table-hint-equivalent-for-mysql

SQL Server WITH (NOLOCK) 如下所示:

SELECT * FROM TABLE_NAME WITH (nolock)

为实现与 MySQL 相同的效果,我们使用SET SESSION 命令更改会话隔离模式。

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
 SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

您也可以通过以下方式实现:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
COMMIT ;

此语句的工作方式类似于 WITH (NOLOCK),即 READ UNCOMMITTED 数据。我们还可以全局设置所有连接的隔离级别:

 SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;

另外,MySQL服务器中还存在两个与隔离级别相关的系统变量:

SELECT @@global.tx_isolation; (global isolation level)
SELECT @@tx_isolation; (session isolation level)

或者在事务内部设置隔离级别:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO

在代码点火器中,您可以使用前两个解决方案包装查询,也可以使用全局选项。

您可以使用以下代码供您参考:

$this->db->query("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE");
$this->db->trans_start();

// your code

$this->db->trans_complete();

更新 1:

您可以在运行语句之前在查询中设置隔离级别。下面是你使用isolation level read uncommited的简单php mysqli代码

//db connection
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');

//set isolation level
$mysqli->query("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");

//your Select Query
$results = $mysqli->query("SELECT * FROM tablename");


while($row = $results->fetch_assoc()) {
    //some statements
}

// Frees the memory associated with a result
$results->free();
$mysqli->query("COMMIT");
// close connection
$mysqli->close();

【讨论】:

  • 数据库交互需要PHP和MySQL形式的示例代码
【解决方案2】:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
COMMIT ;

Reference

【讨论】:

    【解决方案3】:

    只有 InnoDB 存储引擎完全支持事务。它还实现了 Oracle/PostgreSQL 风格的 MVCC,可防止隐式行锁阻塞读取。要在 InnoDB 中读取未提交,请在发出查询之前发出 SET TRANSACTION LEVEL READ UNCOMMITTED

    在 PHP 中这样做的语法如下所示:

    $dbh->exec('SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED');
    $dbh->beginTransaction();
    

    这会将隔离级别设置到下一个COMMITROLLBACK。要使级别更改在会话期间持续存在,请使用

    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    

    改为。

    至于覆盖表或行上的非共享读锁,我不确定这是可能的,我也想不出它会是可取的情况。非共享锁通常是非共享的。

    【讨论】:

    • 数据库交互需要PHP和MySQL形式的示例代码
    • MyISAM 没有事务意识。没有“承诺”。在查询完成之前,整个表都被锁定,因此无法查看“未提交”数据。
    【解决方案4】:

    SELECT 语句以非锁定方式执行,但可能会使用行的早期版本。因此,使用这个隔离级别,这样的读取是不一致的。这也称为脏读。否则,此隔离级别的工作方式类似于 READ COMMITTED。

    可序列化

    这个级别类似于 REPEATABLE READ,但如果禁用自动提交,InnoDB 会隐式地将所有普通的 SELECT 语句转换为 SELECT ... LOCK IN SHARE MODE。如果启用了自动提交,则 SELECT 是它自己的事务。因此,它是只读的,并且如果作为一致(非锁定)读取执行并且不需要阻塞其他事务,则可以序列化。 (如果其他事务修改了选定的行,要强制一个普通的 SELECT 阻塞,禁用自动提交。)

    自动提交

    Command-Line Format --autocommit[=#]
    System Variable Name    autocommit
    Variable Scope  Global, Session
    Dynamic Variable    Yes
    Permitted Values    Type    boolean
    Default ON
    

    自动提交模式。如果设置为 1,则对表的所有更改都会立即生效。如果设置为 0,则必须使用 COMMIT 接受事务或使用 ROLLBACK 取消事务。如果 autocommit 为 0 并且您将其更改为 1,MySQL 将对任何打开的事务执行自动 COMMIT。开始事务的另一种方法是使用 START TRANSACTION 或 BEGIN 语句。看 Section 13.3.1, “START TRANSACTION, COMMIT, and ROLLBACK Syntax”.

    默认情况下,客户端连接以自动提交设置为 1 开始。要使客户端以默认值 0 开始,请通过使用 --autocommit=0 选项启动服务器来设置全局自动提交值。要使用选项文件设置变量,请包含以下行:

    [mysqld]
    autocommit=0
    

    See This also

    【讨论】:

    • 数据库交互需要PHP和MySQL形式的示例代码
    • 我认为你用你的 php 选择的任何东西都不会被提交,除非你提交它。
    【解决方案5】:

    在代码点火器中,您可以在任何请求之前使用以下命令:

    $this->db->simple_query("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
    

    您可以获取有关MySQL isolation level in the documentation 的更多信息。这需要 innoDB 表。

    关于simple_query()的更多信息,根据codeigniter documentation,当查询没有返回结果时使用。

    【讨论】:

    • 数据库交互需要PHP和MySQL形式的示例代码
    • @Helper 那已经是 PHP 和 MySQL。如果您的问题与 codeigniter 无关,则必须使用 mysqli_query() 而不是 $this->db->simple_query()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 2015-07-31
    • 2022-08-04
    • 1970-01-01
    • 2016-08-20
    • 1970-01-01
    • 2015-08-24
    相关资源
    最近更新 更多