From 2edfa4a1f9d91a40824eea66922926b1facd511b Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Fri, 4 Sep 2015 02:05:29 +0200 Subject: [PATCH] MDL-51245 mssql: Diagnose missing READ_COMMITTED_SNAPSHOT mode Without it, transactions are executed in standard READ_COMMITED mode, without snapshoting/row versioning, leading to update conflicts under high concurrency. --- lang/en/error.php | 1 + lib/dml/mssql_native_moodle_database.php | 31 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lang/en/error.php b/lang/en/error.php index 0d58b134a8fe5..dd5ace361c6d7 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -388,6 +388,7 @@ $string['movecategorynotpossible'] = 'You cannot move category \'{$a}\' into the selected category.'; $string['movecategoryownparent'] = 'You cannot make category \'{$a}\' a parent of itself.'; $string['movecategoryparentconflict'] = 'You cannot make category \'{$a}\' a subcategory of one of its own subcategories.'; +$string['mssqlrcsmodemissing'] = 'The database is not using the expected READ_COMMITTED_SNAPSHOT mode which can lead to wrong results, especially under high concurrency scenarios. Please enable it for correct behaviour. You can find more information in the Moodle Docs.'; $string['multiplerecordsfound'] = 'Multiple records found, only one record expected.'; $string['multiplerestorenotallow'] = 'Multiple restore execution not allowed!'; $string['mustbeloggedin'] = 'You must be logged in to do this'; diff --git a/lib/dml/mssql_native_moodle_database.php b/lib/dml/mssql_native_moodle_database.php index c6a6b9c184e26..96df8997718c1 100644 --- a/lib/dml/mssql_native_moodle_database.php +++ b/lib/dml/mssql_native_moodle_database.php @@ -98,6 +98,37 @@ public function get_configuration_help() { return get_string('nativemssqlhelp', 'install'); } + /** + * Diagnose database and tables, this function is used + * to verify database and driver settings, db engine types, etc. + * + * @return string null means everything ok, string means problem found. + */ + public function diagnose() { + // Verify the database is running with READ_COMMITTED_SNAPSHOT enabled. + // (that's required to get snapshots/row versioning on READ_COMMITED mode). + $correctrcsmode = false; + $sql = "SELECT is_read_committed_snapshot_on + FROM sys.databases + WHERE name = '{$this->dbname}'"; + $this->query_start($sql, null, SQL_QUERY_AUX); + $result = mssql_query($sql, $this->mssql); + $this->query_end($result); + if ($result) { + if ($row = mssql_fetch_assoc($result)) { + $correctrcsmode = (bool)reset($row); + } + } + $this->free_result($result); + + if (!$correctrcsmode) { + return get_string('mssqlrcsmodemissing', 'error'); + } + + // Arrived here, all right. + return null; + } + /** * Connect to db * Must be called before other methods.