MySQLのフロントエンドにAccessを使用していて「データ競合」が起こる場合の対処方法。
この記事は備忘録として体験事例を書いているものです。
データ競合
MySQLのフロントエンドにAccessを使用している場合の話。フォームにレコードを呼び出して更新させようとすると「このレコードは他のユーザーによって変更されています。」というようなエラーメッセージが出てレコードが更新されないという現象が起こることがあります。
この体験事例を書いたときにも、あるシステムのあるテーブルデータを更新するときだけ、なぜか「このレコードは他のユーザーによって変更されています。」と表示され何度やってもレコードが更新されないという症状が発生しました。
データ型やODBCの設定は対処したのに
いくつかのサイトで、「データ型がMySQLとAccessでは微妙に解釈が異なる」「ODBCのReturn matching~をレ点チェック入れると解消する」などの解説があり、これらはすべて参考にさせていただいて反映させた上で開発を始めたので、当初は怒らなかったエラーでした。
それなのになぜかある時気づいたらエラーが出るようになったという・・・(T_T)
テーブルのフィールドをひとつひとつ確かめる
そこで、Accessでの設定云々をあきらめ、一旦MySQLのテーブルそのものをチェックしていくことに。手順は以下の通り。
- 該当するテーブルを予めバックアップしていつでも復元できるようにしておく
- 該当テーブルの末尾のフィールドをひとつ削除する。
- Access側でリンクテーブルを更新し(=フィールドがひとつ少なくなった状態のテーブルに更新し)、レコードの更新ができるかどうか?を確かめる。(この場合、フォームを操作しようとするとフィールドが足りなくなっているのでエラーが出る恐れが非常に高い。そこでAccess側でもテーブルを直接呼び出してデータ更新をする)
- 2,3を繰り返し「エラーが出なくなったとき」に削除したフィールドが、今回のエラーの原因だと推定する。
- 一旦、該当するテーブルを完全に削除し、バックアップのテーブルを復元する。
- Access側でリンクテーブルを更新し、元通りのテーブル状態に戻す。
- Access側で、該当するテーブルをリンクテーブルからローカルテーブルへ変換する(変換したテーブルは名前を変更しておく)
- MySQL側で、該当するテーブルの、推定したフィールドだけを削除し、反映させる。
- MySQL側で、削除したフィールドを、もう一度手作業で追加する(フィールド名、データ型などの設定を元通りひとつひとつ手作業で行う)
- Acess側で、該当するテーブルを再々度リンクテーブルマネージャで更新する。
- 10までの手順で、「該当テーブルの、怪しいと思われるフィールドを手作業で作り直した(=ただしこのフィールドの値がすべて空白になっている)、リンクテーブル」と、「元のリンクテーブルからローカルテーブルへ変換したテーブル(つまり怪しいと推測したフィールドの値を保持しているローカルテーブル」が存在することになる。
- ローカルテーブルを開き、怪しいと推察したテーブルのフィールドをすべて選択(縦1列を選択する)して、コピー。
- リンクテーブルの、該当するフィールドへ値をペーストする(値が復旧する)
この手順を行うことで、競合エラーが出なくなりました。
MySQLの運用の過程で、何らか該当するテーブルにエラーが発生したのか、それともAccessでは許容できるがMySQLでは許容できない値が入力されたなどの不測の事態が起きたのか、とにかく今回のデータ競合ではMySQL側のテーブルが破損しているのかな?というような原因でした。
と、いうことで、やはりMySQLのデータバックアップは非常に大事ですねということがわかった備忘録です^^;
これ以外の原因・対処
上記の記事は2017年1月に掲載したものですが、その後、もうひとつ「データ競合」のエラーが起こるケースに気づきました。それは、「フォーム上のエラー」です。
フォームのレコードソースに「TableA」というテーブルを設定していて、該当するレコードを操作するのにVBAで当該レコードを処理しようとする際に、データ競合エラーが起こる場合がありました。
この場合は、フォーム上のイベント「エラー時」にエラーの回避コードを記述すれば回避できます。
記述すべきコードは以下の通り。
If DataErr = 7787 Then
Response = acDataErrContinue
End If
フォーム上の当該レコードを、SQLの実行などで変更・更新しようとするとエラーが起こるため、VBAの方の処理を優先するためのエラー回避です。